My setup is as following. I have a layout component where I add a navigation component and children. I wrap them with my Provider like this
AppLayout.js
<Layout>
<Navigation/>
<main>
{children}
</main>
</Layout>
Now the <Navigation/>
component has access to the data returned by React.useContext(ContextProvider)
.
However a child component of Layout does not! If I try to console.log(state)
in the <Navigation/>
component I get back the actual data as expected.
But when I have a child component like this:
Child.js
<AppLayout>
<div>Some content</div>
</AppLayout>
The state is always undefined. The only way I managed to solve this issue was by wrapping the Provider around the Component in the _app.js
file. Does anyone know how to solve this without wrapping the provider around the <Component/>
from _app.js
file?
That is not possible.
Every component that should have access to one context MUST be descendants of THE SAME context provider.
If you put the context provider inside a wrapper component, and this wrapper component is used in multiple different positions, each instance has a separate context provider, which is a different state. That just does not work.
If you do not want your context provider to be in _app.js, then you may put it inside any child component, but still every component that wants to use the state has to be a descendant of the context provider.
e.g.:
<App>
<NoDoesNotHaveStore />
<ContextProvider store={ myStore }>
<YesDoesHaveStore />
<YesAlsoDoesHaveStore />
</ContextProvider>
</App>
You may wrap the context provider:
const SomeWrapper = function(props){
return <ContextProvider store={ myStore }>
{ props.children }
</ContextProvider>;
};
<App>
<NoDoesNotHaveStore />
<SomeWrapper>
<YesDoesHaveStore />
<YesAlsoDoesHaveStore />
</SomeWrapper>
<NoStoreAgain />
</App>
But not multiple times:
const SomeWrapper = function(props){
return <ContextProvider store={ myStore }>
{ props.children }
</ContextProvider>;
};
<App>
<SomeWrapper>
<HasStoreA />
</SomeWrapper>
<SomeWrapper>
<HasDifferentStoreB />
</SomeWrapper>
</App>
Also note that in Next.js, under certain circumstances, the store might be different on server side vs. client side, or on first render vs. clicking a Next-Link.