how do i wrap 2 routes in a context in react router v6? only these two should be exposed to that context and i cant set the context separately because the context runs some code(useEffect) and if i do that it triggers everytime i switch route, i want it to trigger before i load the 2 routes not after pressing them, but also after i load app.js so app.js loads and the context provider doesnt, then when i one of the 2 routes the context triggers, and when i switch between them it wont trigger is it possible? thanks
return (
<Layout>
<Routes>
<Route path="/*" element={<Navigate replace to='/login'/>} />
<Route path="/pracels" element={<PracelsPage/>} />
<Route path="/search" element={<SearchPracelPage/>} />
<Route path="/login" element={<LoginPage/>} />
</Routes>
</Layout>
);
i want to wrap /pracels and /search with 1 context provider
CodePudding user response:
You can just wrap the routes in one context provider.
Lets say you have a context called AuthProvider
you can use it like this:
return (
<Layout>
<AuthProvider>
<Routes>
<Route path="/pracels" element={<PracelsPage/>} />
<Route path="/search" element={<SearchPracelPage/>} />
</Routes>
</AuthProvider>
<Routes>
<Route path="/*" element={<Navigate replace to='/login'/>} />
<Route path="/login" element={<LoginPage/>} />
<Routes/>
</Layout>
);
Now only the routes in <AuthProvider>
will use your context.
CodePudding user response:
It's counterintuitive, but you can actually just render the auth provider in each <Route>
's element prop, and you'll instantiate a single auth provider, not multiple. Switching between the routes that render an <AuthProvider>
will reuse the existing AuthProvider, not mount and unmount it, and so it will keep its state.
<Routes>
<Route path="/*" element={<Navigate replace to="/login" />} />
<Route
path="/pracels"
element={
<AuthProvider>
<PracelsPage />
</AuthProvider>
}
/>
<Route
path="/search"
element={
<AuthProvider>
<SearchPracelPage />
</AuthProvider>
}
/>
<Route path="/login" element={<LoginPage />} />
</Routes>
See this code sandbox, demonstrating what i mean. Note that the auth provider does not unmount when moving between Pracels and Search, and that any changes made while on one of those pages will persist when moving to the other page
https://codesandbox.io/s/determined-snowflake-y0o80g?file=/src/App.js
How does this work?
The way that <Routes>
and <Route>
are implemented, most of the elements get removed from the page during rendering. So the contents that are actually returned to react as a result of the render process look quite a bit different from what you wrote.
Suppose that the url is currently on /login. In that case, the end result that react sees is just this:
<Layout>
<LoginPage/>
</Layout
Actually... they'll be expanded out into their native dom elements like divs and such. But for brevity i'll leave it like this. The main takeaway though is that <Route>
and <Routes>
are nowhere to be found. Those components are basically just a complicated if
statement, who's job is to pick which elements to include but then to get out of the way.
Next, the user moves from /login to the /pracels page. This rerenders and the result is:
<Layout>
<AuthProvider>
<PracelsPage />
</AuthProvider>
</Layout>
React then reconciles with the previous render. It sees that Layout hasn't changed, so it keeps that. But then it sees the child of layout is a new type of element, an AuthProvider. So it mounts that and its children, the PracelsPage.
Now the important one: the user moves from /pracels to the /search page. The rerender results in:
<Layout>
<AuthProvider>
<SearchPracelsPage />
</AuthProvider>
</Layout>
React does reconciliation. It sees that layout hasn't changed, so it keeps it. It sees that AuthProvider hasn't changed, so it keeps it. The calculations that generated the <AuthProvider>
were different, but react doesn't see that, it just sees the return value.
Inside the AuthProvider is a SearchPracelsPage. That is a change from before, so the PracelsPAge gets unmounted and replaced with SearchPracelsPage. But it will be interacting with the same instance of the AuthProvider