Home > Software engineering >  How to add extra parameters to const PrivateRoute function
How to add extra parameters to const PrivateRoute function

Time:09-27

I have this simple PrivateRoute setup that I'm looking to extend, using react-router-dom 6.3

import { Navigate } from 'react-router-dom';
import { useAppSelector } from '../../../hooks/redux/hooks';

const PrivateRoute = ({ page }: { page: JSX.Element}) => {
  const { isAuthenticated } = useAppSelector((state) => state.auth);
  return isAuthenticated ? page : <Navigate replace to='/login' />
}
export default PrivateRoute

Which gets used as follows:

<Route path='/' element={<PrivateRoute page={<Dashboard/>} />} />

What I would like is to add two new parameters: a 'permissions' parameter as a string array and specify a 'redirect' parameter as a nullable string.

<Route path='/' element={<PrivateRoute page={<Dashboard/>} permissions={['admin']} redirect='' />} />

I tried the following:

const PrivateRoute = ({ page }: { page: JSX.Element}, permissions: string[], redirect?: string) => {
}

It didn't error, but I also couldn't add the two new parameters in as I thought I could as in the 2nd to last example.

How can I achieve this?

CodePudding user response:

React components take up to a single props object as an argument. You need to add the additional props and types to this argument.

interface PrivateRouteProps {
  page: JSX.Element;
  permissions: string[];
  redirect?: string;
}

const PrivateRoute = ({ page, permissions = [], redirect }: PrivateRouteProps) => {
  ...
}

I think you're going about route protection a bit incorrectly though. The more established pattern is to create a layout route that handles checking the authentication status and renders an Outlet component for nested routes or the Navigate component to redirect.

Example:

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

interface PrivateRouteProps {
  permissions: string[];
  redirect?: string;
}

const PrivateRoutes = ({ permissions = [], redirect = "/" }: PrivateRouteProps) => {
  const location = useLocation();

  ...

  if (checkingPermission) {
    return null; // or loading indicator/spinner/etc
  }

  return hasPermission 
    ? <Outlet />
    : <Navigate to={redirect} replace state={{ from: location }} />;
}

...

<Routes>
  <Route element={<PrivateRoute permissions={['admin']} redirect='/login' />}>
    <Route path='/' element={<Dashboard />} />
    ... other protected routes by role
  </Route>

  ... other unprotected routes
</Routes>
  • Related