大家! 想象一下,我有一个组件SomeComponent。每次"b"值更改时,useEffect都会触发,尽管"b"不在其依赖项中
const SomeComponent = () => {
const a = [1, 2, 3] //just an example of dependency. In real life it will be a changing value
const b = useSelector(someValueSelector)
useEffect(() => {
//do some staff
}, [a])
}
有没有办法在某个组件中存储对"a"数组的引用?我知道的唯一方法是创建一个包装器组件并传递
a = useMemo(() => [1, 2, 3], [])
作为道具
<SomeComponent a={a} />
这里的问题是,每次重新渲染时,引用都会发生变化,因此再次触发useEffect
您可以使用SomeComponent
中的useMemo
为a
分配一个记忆值
const SomeComponent = () => {
const a = useMemo(() => [1, 2, 3], []);
const b = useSelector(someValueSelector)
useEffect(() => {
//do some staff
}, [a])
}
正如你可能已经收集到的那样,但对于任何未来的读者来说,这是由于 JavaScript 中的对象相等性。由于对象是通过引用比较的,因此{} === {}
计算结果为false
。
根据您的使用案例,您可以通过以下方式解决此问题:
-
如果值是静态的并且不依赖于 props,请在与组件相同的范围内定义
a
。这样就无需将其声明为useEffect
例程的依赖项:const a = [1, 2, 3] const SomeComponent = () => { useEffect(() => { // do something with `a` }, []) }
- 如果该值是动态的,但更改不应导致组件重新渲染,请使用 ref。 更改 ref 的值不会提示 React 重新渲染组件,并且每次渲染时都会从
useRef()
返回相同的对象:const SomeComponent = () => { const ref = useRef([1, 2, 3]) useEffect(() => { // do something with ref.current }, [ref]) }
- 最后,如果
a
的值是动态的或依赖于可能随时间变化的道具,请使用useMemo
。请注意,useMemo
不是语义保证——React 可能会选择弹出存储的值以释放内存,因此它应该只用作性能优化:const SomeComponent = () => { const a = useMemo(() => [1, 2, 3], []) useEffect(() => { // do something with a }, [a]) }