I know how to implement protected routes in the React-Router V6, but I wanna go a bit more modular approach. My application is large and I want to separate all the role based routes. For example, there will be an "AdminRoutes" component which would contain all the routes for the admin and then I will add it as a "ProtectedRoute" children.
In short, instead of this:
<Routes>
<Route element={<ProtectedRoutes />}>
<Route path='/admin' element={<AdminPage />} />
<Route path='/profile' element={<Profile />} />
</Route>
</Routes>
I want to have this:
<Routes>
<Route element={<ProtectedRoutes />}>
<AdminRoutes />
</Route>
</Routes>
Where the AdminRoutes
component would return the admin routes like:
export function AdminRoutes() {
return (
<>
<Route path='/admin' element={<AdminPage />} />
<Route path='/profile' element={<Profile />} />
</>
)
}
Note: the ProtectedRoutes
component will return children (outlet) or navigate to a different route based on some logic
Currently it's giving me error that "Uncaught Error: All component children of <Routes>
must be a <Route>
or <React.Fragment>
".
Is what I am saying possible? If you know any other better approach than this, I would also wanna know that.
Currently it's giving me error that "Uncaught Error: All component children of
<Routes>
must be a<Route>
or<React.Fragment>
"
You can't render directly the Route
component, it must have either a Routes
component as its parent, or another Route
component in the case of nested routes. AdminRoutes
is neither a Route
or React.Fragment
component so it cannot be rendered as a child of Routes
or Route
.
In AdminRoutes
wrap the routes in the Routes
component so it can correctly render the descendent routes.
export function AdminRoutes() {
return (
<Routes>
<Route path="/admin" element={<AdminPage />} />
<Route path="/profile" element={<Profile />} />
</Routes>
);
}
Is what I am saying possible?
Yes, but since you are converting nested routes into descendent routes, the main router needs to render AdminRoutes
on a route as well, not alone by itself as a child of Route
(for the same reason above).
Render AdminRoutes
as a routed component on path="/*"
with the trailing splat so all descendent routes (e.g. routes rendered in component's Routes
component) can also be matched and rendered.
<Routes>
<Route element={<ProtectedRoutes />}>
<Route path="/*" element={<AdminRoutes />} />
</Route>
</Routes>