0

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

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

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

  return <div />
}

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

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

const someContextValue = useMemo(useSomeContext, [useSomeContext])

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

4

1 回答 1

6

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

变量在someContextValue组件内部定义。

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

useEffect将通过它们的实例而不是它们内部的值来比较引用类型。

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

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

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

const { someStateValue } = useSomeContext()

useEffect(() => {
  someStateValue()
}, [someStateValue]);
于 2020-05-11T20:28:41.157 回答