Home > Enterprise >  How to "wrap" <Route> component so that it can be used inside <Router> in Reac
How to "wrap" <Route> component so that it can be used inside <Router> in Reac

Time:03-23

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 ...
  • Related