反应钩子参考值比较



大家! 想象一下,我有一个组件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中的useMemoa分配一个记忆值

const SomeComponent = () => {
const a = useMemo(() => [1, 2, 3], []); 
const b = useSelector(someValueSelector)
useEffect(() => {
//do some staff
}, [a])
}

正如你可能已经收集到的那样,但对于任何未来的读者来说,这是由于 JavaScript 中的对象相等性。由于对象是通过引用比较的,因此{} === {}计算结果为false

根据您的使用案例,您可以通过以下方式解决此问题:

  1. 如果值是静态的并且不依赖于 props,请在与组件相同的范围内定义a。这样就无需将其声明为useEffect例程的依赖项:

    const a = [1, 2, 3]
    const SomeComponent = () => {
    useEffect(() => {
    // do something with `a`
    }, [])
    }
    
  2. 如果该值是动态的,但更改不应导致组件重新渲染,请使用 ref。 更改 ref 的值不会提示 React 重新渲染组件,并且每次渲染时都会从useRef()返回相同的对象:
    const SomeComponent = () => {
    const ref = useRef([1, 2, 3])
    useEffect(() => {
    // do something with ref.current
    }, [ref])
    }
    
  3. 最后,如果a的值是动态的或依赖于可能随时间变化的道具,请使用useMemo。请注意,useMemo不是语义保证——React 可能会选择弹出存储的值以释放内存,因此它应该只用作性能优化:
    const SomeComponent = () => {
    const a = useMemo(() => [1, 2, 3], [])
    useEffect(() => {
    // do something with a
    }, [a])
    }
    

相关内容

  • 没有找到相关文章

最新更新