我在 Redux 中有一个状态对象,并且正在使用 useSelector 和 deepEqual(来自 fast-deep-equal)来检测更改。然后在当前状态上使用备忘录。令人费解的是,尽管状态似乎没有改变,但 useMemo 却被调用了。
这是我的代码结构:
import deepEqual from "fast-deep-equal"
export function useMyState() {
const values = useSelector(
(store) => store.prop1,
(a, b) => { // comparison function arg to useSelector
const equal = deepEqual(a, b)
if (!equal) {
console.log("COMPARE FALSE")
}
return equal
}
)
useEffect(() => {
console.log("MOUNTED")
}, [])
return useMemo(() => {
console.log("VALUES CHANGED", JSON.stringify(values))
return {
values,
method1() {
// do something
}
}
}, [values])
}
我确认 MOUNTED
只输出一次,即使 VALUES CHANGED
没有输出,COMPARE FALSE
也会输出。这怎么可能……?
也许如果组件碰巧作为父渲染的一部分呈现,它总是从存储中获取当前对象(这不是 ===
前一个值),而 useSelector
比较 fn 仅用于防止重新-当状态没有改变时组件的渲染(隔离)?如果是这种情况,防止 useMemo
在值深度相等时运行的最佳做法是什么?
代码沙盒:https://codesandbox.io/s/redux-state-change-zdxzs
当有两个 useSelector
时会出现问题,其中一个被触发,导致重新渲染。然后组件认为另一个 useSelector
的结果已经改变,即使它没有根据选择器本身的测试 (deepEqual
)。
要复制上面的链接,请单击增量按钮几次 - 组件已呈现,但未更改待办事项。然后单击“重新创建”按钮并再次增加。即使项目没有根据 deepEqual
改变,文本 TODOS CHANGED!
也会输出。
谢谢