javascriptreactjsreact-context

set react context value from child component


I create a React Context like: context.ts file

import { createContext } from "react";

const Context = createContext({
  error: "",
  setError: () => {},
});

export default Context;

I get a child component which need to set a value into this context: component.tsx

import Context from MyContext;

function child() {
  const [error, setError] = useState();

 useEffect(() => {
  setError("foo");
});

return(
<Context.Provider value={{error, setError}}>
// Some unrelated stuff 
</Context.Provider>
);

From parent child I try to display context value:

import routes from "routes";

function App() {
  const routing = useRoutes(routes);
  const { error, setError } = useContext(Context);

  useEffect(() => {
console.log("error : ", error);
});

return (
 {routes}
);

routes.tsx:

const routes = [
  {
    path: "/",
    element: <Index />,
  },
];

export default routes;

Index.tsx:

function Index() {
  return <child/>; 
}

export default Index;

I can see the output of console: error :

So the child component never set, or parent component never received new context value. How to pass context value set from child component, to parent component ? (maybe it's an issue with routing ? )


Solution

  • The issue here is that the Context.Provider is inside the child component and the parent component is trying to access the context value.

    The context value is not available to the parent because the parent is not wrapped inside the Context.Provider. You need to wrap both components with Context.Provider in order to be able to use it in both.

    Thus:

    App.tsx:

    function App() {
      const [error, setError] = useState("");
      const routing = useRoutes(routes);
    
      useEffect(() => {
        console.log("error : ", error);
      }, [error]);
    
      return (
        <Context.Provider value={{ error, setError }}>
          {routing}
        </Context.Provider>
      );
    }
    

    Child.tsx:

    function Child() {
      const { error, setError } = useContext(Context);
    
      useEffect(() => {
        setError("foo");
      }, []);
    
      return (
        <div>
          // Some stuff 
        </div>
      );
    }