Workaround for a React-router Route wrapper

Viewed 232

I'm trying to create a wrapper for the Route component of React Router, something like this:

import { Navigate, Route } from 'react-router-dom'

function MSRoute({ path, element, isStaff = false }) {
  return (
    <>
      { isStaff
        ? (
          <Route
            path={path}
            element={element}
          />
        ) : (
          <Route
            path="*"
            element={<Navigate to="/" />}
          />
        )
      }
    </>
  )
}

export default MSRoute

Basically because I need to restrict some routes for certain types of users, but I'm getting the following error:

Uncaught Error: [MSRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

Is there any way of doing this? Any clean workaround?

regards

1 Answers

The error Uncaught Error: [MSRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment> is informing you that Route components can only be rendered by a Routes or other Route component. MSRoute is neither a Route nor React.Fragment, so it can't be rendered as a child of the Routes component.

It seems you are wanting to either render the routed component or redirect based upon the isStaff prop value. In order for MSRoute to be a wrapper component it needs to wrap and render the children prop.

Example:

import { Navigate } from 'react-router-dom'

function MSRoute({ children, isStaff = false }) {
  return isStaff ? children : <Navigate to="/" replace />;
}

Usage:

<Route
  path={path}
  element={(
    <MSRoute isStaff={isStaff}>
      {element}
    </MSRoute>
  )}
/>

If you have the need to wrap several routes with this isStaff check then you can convert MSRoute into a layout component that renders an Outlet for nested routes instead of rendering a single child component.

import { Navigate, Outlet } from 'react-router-dom'

function MSRoute({ isStaff = false }) {
  return isStaff ? <Outlet /> : <Navigate to="/" replace />;
}

Usage:

<Route element={<MSRoute isStaff={isStaff} />}>
  <Route path={path} element={element} />
  ... other routes
</Route>
Related