防止子组件在上下文提供者下面重新渲染并带有备忘录

And*_*dré 7 memoization reactjs react-native react-context

我在 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>
  );
});
Run Code Online (Sandbox Code Playgroud)

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

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

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

我的 App.js 如下所示:

<ChatProvider>
  <Authenticator />
</ChatProvider>
Run Code Online (Sandbox Code Playgroud)

Mar*_*ton 8

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

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

  return (
    <ChatDispatchContext.Provider value={setMyChat}>
      <ChatValueContext.Provider value={myChat}>
        {children}
      </ChatValueContext.Provider>
    </ChatDispatchContext.Provider>
  )
}
Run Code Online (Sandbox Code Playgroud)

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

const Authenticator = React.memo(() => {
  const setMyChat = useContext(ChatDispatchContext)

  return (
    <Button
      title="click me"
      onPress={() => setMyChat({ text: "hello" })}
    ></Button>
  )
})
Run Code Online (Sandbox Code Playgroud)