是否需要 useMemo 来通过 reactjs 中的上下文 API 管理状态?

Posted

技术标签:

【中文标题】是否需要 useMemo 来通过 reactjs 中的上下文 API 管理状态?【英文标题】:is useMemo required to manage state via the context API in reactjs? 【发布时间】:2020-09-25 13:22:01 【问题描述】:

我想了解this (mostly very helpful) article,它描述了如何使用 react 的上下文 API 来管理应用程序级状态。对于一个简单的应用程序(在本例中是一个基本的计数器应用程序),它使用以下解决方案:

const CountContext = React.createContext()

function CountProvider(props) 
  const [count, setCount] = React.useState(0)
  const value = React.useMemo(() => [count, setCount], [count])
  return <CountContext.Provider value=value ...props />

提供上下文,然后是下面的钩子,它可以在组件树的某个地方使用:

function useCount() 
  const context = React.useContext(CountContext)
  if (!context) 
    throw new Error(`useCount must be used within a CountProvider`)
  
  return context

我的问题:

我很难理解为什么这里需要useMemo 挂钩。这里没有涉及特别繁重的计算,所以我不确定我们为什么要记住这些值。如果上下文提供程序如下所示,这不是同样有效吗:

function CountProvider(props) 
  const [count, setCount] = React.useState(0)
  return <CountContext.Provider value=value ...props />

我觉得我可能缺少一些东西!

【问题讨论】:

顺便说一句,我会从你的依赖数组中删除setCount,因为 React 保证这个函数永远不会更新。 【参考方案1】:

有一个非常简单的理论来解释为什么要使用 useMemo 来记忆返回给 Context Provider 的值。当您将值作为对象或数组传递给上下文提供程序时,

return <CountContext.Provider value=state, setCount ...props />

return <CountContext.Provider value=[state, setCount] ...props />

本质上发生的是,每次 CountProvider 组件重新呈现对对象或数组的新引用时,都会将其作为值传递给 CountContext.Provider,因此即使实际值可能没有改变,上下文消费者也会重新呈现因为值的参考检查失败

现在您可能需要也可能不需要 useMemo,具体取决于您在 ContextProvider 中的逻辑。例如,在您的情况下,CountContext 仅使用一种状态,即计数并将其传递给子级,并且如果CountContext 是***元素之一,除了计数更改之外不会重新渲染那么在这种情况下,您是否使用useMemo 没有区别,因为来自useMemo 的返回值的引用也会在计数更改时更新

但是,如果您有某些 CountProvider 的父级可能导致 CountProvider 重新渲染,则 useMemo 记忆上下文值会派上用场,以避免重新渲染所有上下文消费者

【讨论】:

谢谢。是的,这很有意义, 很高兴能帮上忙 :-)【参考方案2】:

调用 setCount 总是会重新渲染一个组件

我相信即使将相同的值传递给函数,调用 setCount 也会始终重新呈现。

但是行

const value = React.useMemo(() => [count, setCount], [count])

除非计数值不同,否则将停止调用 setCount。从而减少重新渲染并提高性能。

您可以通过在其中放置日志并查看组件在使用和不使用 useMemo 时的呈现方式来测试这个理论。

【讨论】:

谢谢。是的,这是有道理的。这个答案和另一个答案都给出了记住上下文值的充分理由。我接受了另一个答案,但它们似乎都是正当理由。 当然,另一个答案提供了更多深度。我很高兴能帮助一个反应爱好者! 我和作者有同样的问题,不幸的是这个建议对我不起作用:(

以上是关于是否需要 useMemo 来通过 reactjs 中的上下文 API 管理状态?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 reactjs 从谷歌驱动器获取文件?

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

React Hooks-useMemo篇