重新渲染时 useContext 值发生变化

useContext value changes on rerenders

所以我有一个看起来像

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

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

  return <div />
}

只要组件重新呈现,useEffect 就会被触发,即使 someContextValue 并没有真正改变。

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

const someContextValue = useMemo(useSomeContext, [useSomeContext])

现在 someContextValue 在重新呈现时不会改变。但我觉得这不太对。执行此操作的正确方法是什么?

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

someContextValue 变量在组件内部定义。

该组件是一个函数,当函数运行时,其中定义的值将被定义。例如,如果您的上下文 returns 是一个包含状态值的对象,那么该对象与之前渲染的对象是不同的实例,因此您的 useEffect 会运行。

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

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

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

这就是为什么在使用上下文时,您应该解构上下文对象并引用对象中的值,它们是从 useState 钩子 内部 上下文传递的状态值,或者在上下文中定义的值在您的消费组件重新呈现时不会重新定义(因为上下文不会在这种情况下重新渲染):

const { someStateValue } = useSomeContext()

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