I created <RequireAuthRoute>
which simply either returns its children or navigates to /login
. However the way it is being used doesn't satisfy me. Take a look at this fragment:
<Route
path=''
element={
<RequireAuthRoute>
<Explorer />
</RequireAuthRoute>
}
/>
So yes - technically it works but what I wanted to do is to create wrapper for <Route>
component so it would end up looking like this:
<ProtectedRoute path='' element={<Explorer/>}/>
Whats blocking me is react-router
itself which tells me that <Router>
direct child can only be <Route>
component. Any workarounds?
CodePudding user response:
Custom route components aren't valid in react-router-dom@6
like what was commonly used in v5.
<ProtectedRoute path='....' element={<Explorer />} />
The above will throw an invariant violation because only Route
and React.Fragment
are valid children of the Routes
component, and Route
components can only be rendered directly by the Routes
component or another Route
component.
If using wrapper components such as RequireAuthRoute
is insufficient:
<Route
path='....'
element={
<RequireAuthRoute>
<Explorer />
</RequireAuthRoute>
}
/>
Then the other common v6 pattern is to use layout routes that render an Outlet
component for nested routes instead of a children
prop.
Example:
import { Navigate, Outlet, useLocation } from 'react-router-dom';
const AuthLayout = () => {
const location = useLocation();
... business logic ...
return isAuthenticated
? <Outlet />
: <Navigate to="/login replace state={{ from: location }} />
};
Then wrap and render the routes you want to protect with this layout route:
<Route element={<AuthLayout />}>
<Route path='....' element={<Explorer />} />
... other protected routes ...
</Route>
... other unprotected routes ...