【问题标题】:prevent child component to re-render below context provider with memo防止子组件在带有备忘录的上下文提供程序下重新渲染
【发布时间】:2021-04-10 19:55:20
【问题描述】:

我在 React 中使用上下文提供程序在多个组件之间共享数据。但是,由于一个值​​从我的一个子组件中发生了变化,它会重新呈现我的所有其他组件,这在一定程度上会导致性能问题。所以我想阻止我的子组件重新渲染。我尝试使用 React.memo() 但每当我设置 Context Provider 的状态时它仍然在渲染。

const Authenticator = React.memo(() => {
  
  const [myChat, setMyChat] = useContext(ChatContext);

  console.log("rerender"); // gets called everytime on click
  return (
    <Button
      title="click me"
      onPress={() => setMyChat({ text: "hello" })}
    ></Button>
  );
});

我的上下文提供程序如下所示:

const ChatProvider = ({ children }) => {
  const [myChat, setMyChat] = useState([]);

  return (
    <ChatContext.Provider value={[myChat, setMyChat]}>
      {children}
    </ChatContext.Provider>
  );
};

我的 App.js 看起来像这样:

<ChatProvider>
  <Authenticator />
</ChatProvider>

【问题讨论】:

    标签: reactjs react-native memoization react-context


    【解决方案1】:

    React.Memo 没有帮助,因为您正在调用 useContext 钩子,这将导致组件在每次来自提供程序的值发生更改时重新呈现。您应该考虑将上下文拆分为两个单独的上下文:一个用于值,一个用于状态更新器。

    const ChatProvider = ({ children }) => {
      const [myChat, setMyChat] = useState([])
    
      return (
        <ChatDispatchContext.Provider value={setMyChat}>
          <ChatValueContext.Provider value={myChat}>
            {children}
          </ChatValueContext.Provider>
        </ChatDispatchContext.Provider>
      )
    }
    

    然后,将您的 Authenticator 组件更新为以下内容:

    const Authenticator = React.memo(() => {
      const setMyChat = useContext(ChatDispatchContext)
    
      return (
        <Button
          title="click me"
          onPress={() => setMyChat({ text: "hello" })}
        ></Button>
      )
    })
    

    【讨论】:

    • 感谢您的回答。我仍然不是 100% 确定我理解了,因为 1)如何在我的 ValueContext 中从 Dispatch Provider 设置我的状态? 2)由于调度提供者高于价值提供者,它也会重新渲染孩子吗?可以
    • 1.调用setMyChat 将更新ChatProvider 中的状态值,该值将传递给使用ChatDispatchContext 的组件。 2. 提供者的顺序无关紧要。重要的是您的Authenticator 组件正在使用一个不会改变的上下文值(setMyChat)。这与React.memo 结合使用将防止组件重新渲染。
    • 是@MarkSkelton 的唯一方法吗?没有机会让他们进入同一个提供商?尝试使用 useCallback 包装上下文的方法,但没有成功。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 2019-10-30
    • 2019-07-23
    • 2020-11-06
    • 2020-08-19
    • 2020-03-09
    相关资源
    最近更新 更多