有没有办法让上下文仅在其数据更改时重新渲染?

Posted

技术标签:

【中文标题】有没有办法让上下文仅在其数据更改时重新渲染?【英文标题】:Is there a way to make context only re-render if its data changes? 【发布时间】:2021-01-01 19:11:26 【问题描述】:

如下图所示,我有一个基本的反应上下文设置。

我希望使用上下文的子组件只应在上下文数据更改时重新渲染,但我发现情况并非如此。

如果我更新与上下文无关的调用setData2,则会在Container 上触发状态更新,随后触发重新计算并导致消费子更新。

有问题的子组件已经在使用React.memo,所以它只会在它的useContext 钩子引导它时更新。但是当Container 更新时,上下文也会更新,即使data1 没有改变。

有办法解决吗?

const Container = () => 
  const [data1, setData1] = useState(...);
  const [data2, setData2] = useState(...);

  return (
    <MyContext.Provider value= data1, setData1 >
     // child component hierarchy
    </MyContext.Provider>
  );
;

【问题讨论】:

【参考方案1】:

为防止子组件在上下文状态更改时重新渲染,您应该通过children 属性将子组件传递给上下文提供程序:

// Define the provider component
const MyContextProvider = ( children ) => 
  const [data1, setData1] = useState(...);
  const [data2, setData2] = useState(...);

  return (
    <MyContext.Provider value= data1, setData1 >
     children
    </MyContext.Provider>
  );
;

然后在你的应用程序的某个地方,渲染提供者:

// Render the provider component
const App = () => 
  return (
    <MyContextProvider>
     // child component hierarchy
    </MyContextProviderr>
  );
;

要访问提供者状态,孩子应该使用useContext(MyContext) 钩子。

没有必要使用React.memo。 React 知道,当使用 children 属性渲染子组件时,子组件不需要重新渲染,因为它们不可能受到本地状态变化​​的影响。

【讨论】:

【参考方案2】:

您可以将不想重新渲染(由其他不相关状态触发)的子组件包装在具有相关依赖项的 useMemo 中 - 仅针对该子组件

const Container = () => 
  const [data1, setData1] = useState(...);
  const [data2, setData2] = useState(...);

  const rerenderInCertainConditions = useMemo(() => (
    <MyContext.Provider value= data1, setData1 >
     // child component hierarchy
    </MyContext.Provider>
  ), [data1])

  return (
    rerenderInCertainConditions
  );
;

Codesandbox 演示

【讨论】:

以上是关于有没有办法让上下文仅在其数据更改时重新渲染?的主要内容,如果未能解决你的问题,请参考以下文章

React Context API似乎重新渲染每个组件

上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染

React 子组件不会在其状态更改时重新渲染

有没有办法让屏幕阅读器在渲染元素时只宣布一次?

等待反应上下文后组件不重新渲染

如何让 CKEditor 用 CSS 渲染文本?