【问题标题】: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>
  );
};

【问题讨论】:

    标签: reactjs react-context react-lifecycle use-context


    【解决方案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 演示

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-01
        • 2021-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-04
        • 1970-01-01
        相关资源
        最近更新 更多