zustand的useShallow hook到底有什么优势?
使用zustand获取状态大概有三种:
- const store = useZustand()
- const {xxx} = useZustand(state => state.xxx)。
- const {xxx} = useZustand(useShallow(stste => state.xxx))
第一种因为会在组件导入所有状态,会导致组件频繁re-render 所以不建议使用。但是zustand文档中建议使用的useShallow 我始终不理解它到底有什么优势
第二种获取状态的方式叫做 selector,selector和useShallow的区别 文档中介绍说是 selector比对采用严格比较 就是===,而useShallow是浅层比较 只比较状态的引用 也就是==。但是这两种我觉得在zustand里没有任何区别。因为zustand在修改一个对象类型状态时 都是会返回一个新对象 而不是直接修改这个对象本身。那么严格比较和浅层比较就没有任何意义了 因为每次状态的引用都会发生变化。请教大神 哪些情况下 是必须使用useShallow的?
我在这里抛砖引玉下:
// store.js
const useZustand = create((set) => {
userinfo: {
name: '',
sex: ''
},
setUserinfo: (payload) => {
set(state => ({...state.userinfo, ...payload}))
}
})
现在我有这么一个store,然后我在组件内使用:
// index.jsx
import useZustand from './store.js'
import {useShallow} from 'zustand/react/shallow'
// 这两种写法 都能达到只有userinfo变化时 重新渲染组件。但是还有其他差别吗?
const userinfo = useZustand(state => state.userinfo)
const userinfo = useZustand(useShallow(state => state.userinfo))
我在react中 找不出 严格比较和浅层比较的区别。因为都是返回新的对象 就算是 对象嵌套对象。这种情况下 我分别测试 selector和useShallow 发现两者表现并无区别。我想知道 有哪些情况下 必须使用useShallow?
首先这句话就不对。 zustand 比较是用的
Object.is
而不是===
;而useShallow
浅比较如果是数组,那就遍历 +Object.is
;如果是对象,那就Object.entries
后再遍历 +Object.is
。其次你提到这种 immutable 的工作方式本身是对的,但结论不对。因为你没有考虑到一个场景:返回的这个新对象、其浅层属性依然等于原对象的各属性。比如原题里那个 userinfo,更新时你是 set 回去一个新的对象了,这个对象跟原对象的引用不同是没错,可若是这个新的 userinfo.name 和 userinfo.sex 和之前完全相同呢?
一个例子:传送门
P.S. React Playground 网站被墙,需要魔法才能访问,你懂的