react-router
react-router copied to clipboard
[Bug]: Context prop in Outlet is not working with `index` routes.
What version of React Router are you using?
6.1.1
Steps to Reproduce
Setup project using below nested routes.
useRoutes([
{
path: '/',
element: <Layout />,
children: [
{
path: 'user',
children: [
{ index: true, element: <User /> },
{ path: 'add', element: <AddUser /> },
],
},
],
},
])
and then use <Outlet context={data} /> in <Layout/>
Expected Behavior
Fetch data using useOutletContext hook.
Actual Behavior
Getting undefined with useOutletContext hook.
When context pass to Outlet component, it only can be obtain in child route.
In the code above, the User component is the grandchild component of Layout, so it could not obtain the context prop.
@timdorr If Outlet component don't have context prop, we can use React.useContext(RouteContext).outlet directly and not wrap with OutletContext.Provider, so the descendant components can get the context prop.
In now, only the child component can get the context prop.
You should be using the new useOutletContext(), not trying to access the route context directly.
@liuhanqu thanks for response, if all nested child can access context then this feature make more sense.
Yes @timdorr I'm using useOutletContext() to access context.
I use react-router-dom v6.0.2 does it support useOutletContext()
No, that is new as of 6.1.0. Please upgrade to a newer version, as you'll also get some bug fixes included.
Hi just to confirm, is it currently possible to access a parent's context from a grandchild route?
I mean this kind of situation:
<Routes>
<Route path="/" element={<Outlet context={{ someKey: 1 }} />}>
<Route path="child" element={<Outlet context={{ otherKey: 1 }} />}>
<Route index element={<GrandChildPage />} />
</Route>
</Route>
</Routes>
then can we access the context containing someKey from GrandChildPage?
@tmokmss I believe accessing the context from GrandChildPage is not working with Outlet in this package for now might be doable in future.
To perform that you need to create custom Outlet using useOutlet hook with Context Provider.
Hi @umarjavedse thanks. Yeah I actually tried similar code as above but it did not work. As a workaround I found a way like this (manually inheriting a parent's context in a child context):
<Routes>
<Route path="/" element={<Outlet context={{ someKey: 1 }} />}>
<Route path="child" element={<Outlet context={{ ...useOutletContext(), otherKey: 1 }} />}>
<Route index element={<GrandChildPage />} />
</Route>
</Route>
</Routes>
This issue has been automatically marked stale because we haven't received a response from the original author in a while 🙈. This automation helps keep the issue tracker clean from issues that are not actionable. Please reach out if you have more information for us or you think this issue shouldn't be closed! 🙂 If you don't do so within 7 days, this issue will be automatically closed.
Going to close this out as "working as expected" after chatting with @ryanflorence and @jacob-ebey.
<Outlet context> is really just a way to pass "props" to the direct child element since you aren't in charge of rendering the element itself - #7495
const routes = [{
path: '/parent',
element: <Parent />,
children: [{
path: 'child',
element: <Child />
}],
}];
function Parent() {
// Since you can't do <Child prop={{ some: "value }} /> here, you can instead do:
return <Outlet context={{ some: "value" }} />
}
function Child() {
// Instead of receiving a `prop`, you can get the parent value from context
let obj = useOutletContext();
// obj => { some: "value" }
}
If you need to provide something for deeper access through multiple intermediate Routes - then that's what normal React.Context is for and there's no need to leverage an Outlet context abstraction.