简体   繁体   中英

react context update not re-rendering component

According to the react documentation for context provider :

All consumers that are descendants of a Provider will re-render whenever the Provider's value prop changes.

I am trying to update a context value from a sibling component (B) and read that update from sibling component (A).

Heres a simple example of what im trying:

import { useState, useContext, createContext } from "react";

export const AnalyseCtx = createContext({ greeting: "hello" });

export default function App() {
  const [context, setContext] = useState({ greeting: "hello" });

  console.log("rendering App");

  return (
    <div className="App">
      <AnalyseCtx.Provider value={{ context, setContext }}>
        <ComponentA />
        <ComponentB />
      </AnalyseCtx.Provider>
    </div>
  );
}

function ComponentA() {
  const analyseContext = useContext(AnalyseCtx);
  console.log("rendering ComponentA");
  return (
    <h4>I display the context value: {analyseContext.context.greeting}</h4>
  );
}

function ComponentB() {
  console.log("rendering ComponentB");
  const analyseContext = useContext(AnalyseCtx);
  analyseContext.setContext((prevState) => {
    prevState.greeting = "updated greeting";
    console.log("updated greeting: ", prevState);
    return prevState;
  });

  return <h4>I update context value</h4>;
}

I have also created a codesandbox to demonstrate the issue as well.

Sorry if this is a stupid question, but I've been stuck on this problem for a whole day. Thanks!

Component B is mutating the state object instead of returning a new state object reference. Shallow copy the previous state object into a new object reference and overwrite the properties you want to update.

Another issue is that component B is updating the context value as an unintentional side-effect. The update should be done from the useEffect hook so it's unconditionally enqueueing state updates and creating conditions for infinite render looping.

function ComponentB() {
  const { setContext } = useContext(AnalyseCtx);

  useEffect(() => {
    setContext(state => ({
      ...state,
      greeting: "updated greeting",
    }));
  }, []);

  return <h4>I update context value</h4>;
}

编辑 react-context-update-not-re-rendering-component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM