I'm trying to provide dynamic custom props to a React Router Route definition using the newest React Router 6.4. I can't find any examples to showcase how I can accomplish this. These would be props that are provided from the parent component of the RouterProvider
declaration.
An example from official documentation for 6.0 - 6.3:
// Ah, nice and simple API. And it's just like the <Suspense> API!
// Nothing more to learn here.
<Route path=":userId" element={<Profile />} />
// But wait, how do I pass custom props to the <Profile>
// element? Oh ya, it's just an element. Easy.
<Route path=":userId" element={<Profile animate={true} />} />
In 6.4, your route definition looks like something like:
// How do I provide animate state from App component to Policy component?
const router = createBrowserRouter([{ path: '/', element: <Profile animate={animate} /> }];
export function App() {
const [animate, setAnimate] = useState(true);
return <RouterProvider router={router} />
}
In the example you provided you are already passing an animate
prop to the routed component. RRDv6.4.0 didn't change the Route
component API. It seems your question is really rather about passing a dynamic prop value when the route is accessed.
Move the router
declaration into the App
component so the animate
state is in scope.
Example:
function App() {
const [animate, setAnimate] = useState(true);
const router = createBrowserRouter([
{ path: "/", element: <Profile animate={animate} /> } // <-- pass prop value
]);
return (
<div className="App">
...
<RouterProvider router={router} />
</div>
);
}
To avoid recreating the router
each time the parent component rerenders you could memoize it with the useMemo
hook.
function App() {
const [animate, setAnimate] = useState(true);
const router = useMemo(() => {
return createBrowserRouter([
{ path: "/", element: <Profile animate={animate} /> }
]);
}, [animate]);
return (
<div className="App">
...
<RouterProvider router={router} />
</div>
);
}
Another alternative would be to move the state into a layout route and pass down the state via the layout route's Outlet
context provider. Consumers use the useOutletContext
hook to access the provided value. This means the router
declaration can be moved out of the React component and be provided as a stable reference.
Example:
const Profile = () => {
const { animate } = useOutletContext();
...
return (
...
);
};
const AppLayout = () => {
const [animate, setAnimate] = useState(true);
return (
<>
...
<Outlet context={{ animate, /* other values */ }} />
...
</>
);
};
const router = createBrowserRouter([
{
element: <AppLayout />,
children: [{ path: "/", element: <Profile /> }]
}
]);
export default function App() {
return (
<div className="App">
<RouterProvider router={router} />
</div>
);
}