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 ? )
2
Answers
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 withContext.Provider
in order to be able to use it in both.Thus:
App.tsx:
Child.tsx:
(React official documentation)
The component which sets the Context up – by using
<Context.Provider
– needs to be above the one that reads it.Context.Provider
needs to be an ancestor (e.g. direct parent) of whatever callsuseContext
. In your case it’s exactly the opposite.You need to swap things around:
<Context.Provider
to the parent componentuseContext
to the child.Parent
Child:
(additionally I swapped
value={{ error, setError }}
tovalue={[ error, setError ]}
and
const { error, setError }
toconst [ error, setError ]
as I’d reccommend to preserve the convetion introduced by
useState
)