useContext 值在重新渲染时发生变化

0 reactjs react-hooks use-context

所以我有一个看起来像这样的组件

const App = () => {
  const someContextValue = useSomeContext();  //custom hook that calls useContext

  useEffect(() => {
    someContextValue()
  }, [someContextValue]);

  return <div />
}
Run Code Online (Sandbox Code Playgroud)

每当组件重新渲染时,即使 someContextValue 并未真正更改,也会触发 useEffect。

我通过使用 useMemo 解决了这个问题

const someContextValue = useMemo(useSomeContext, [useSomeContext])

现在 someContextValue 在重新渲染时不会改变。但我感觉这不太对劲。这样做的正确方法是什么?

JMa*_*ine 7

如果您从上下文返回对象{}或数组,则上下文值已更改。[]

该someContextValue变量在组件内部定义。

该组件是一个函数,当函数运行时,它内部定义的值就会被定义。例如,如果您的上下文返回一个包含状态值的对象,则该对象与上一个渲染中的对象是不同的实例,因此您的useEffect运行。

useEffect将通过实例而不是其中的值来比较引用类型。

当您调用 时useSomeContext(),您正在创建一个新对象,并且每次渲染组件时都会发生这种情况。

这与来自 的状态值不同useState,其中状态值不会被重新定义。钩子useState维护该值的相同实例,因此不会每次都重新创建,并且会useEffect看到状态值是相同的实例。

这就是为什么在使用 context 时,您应该解构context 对象并引用对象内部的值,这些值要么是从context内部的useState 钩子传递的状态值,要么是 context 内部定义的值,当您使用时不会重新定义该值。组件重新渲染(因为在这种情况下上下文不会重新渲染):

const { someStateValue } = useSomeContext()

useEffect(() => {
  someStateValue()
}, [someStateValue]);
Run Code Online (Sandbox Code Playgroud)