prevent child component to re-render below context provider with memo

Viewed 2850

I am using a context provider in React to share data across several components. However since a value gets changed from one of my subcomponents, it rerenders all of my other components which partly leads to performance issues. So I want to prevent my child components to rerender. I tried using React.memo() but it's still rendering whenever I set the state of the 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>
  );
});

My Context Provider looks like this:

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

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

My App.js looks like this:

<ChatProvider>
  <Authenticator />
</ChatProvider>
1 Answers

React.Memo doesn't help since you are calling the useContext hook which will cause the component to re-render every time the value from the provider changes. You should consider splitting your context into two separate contexts: one for the value, one for the state updater.

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

  return (
    <ChatDispatchContext.Provider value={setMyChat}>
      <ChatValueContext.Provider value={myChat}>
        {children}
      </ChatValueContext.Provider>
    </ChatDispatchContext.Provider>
  )
}

Then, update your Authenticator component to the following:

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

  return (
    <Button
      title="click me"
      onPress={() => setMyChat({ text: "hello" })}
    ></Button>
  )
})
Related