Search code examples
reactjstypescriptreact-router-dom

How to use Protected Routes with react-router-dom V6 and typescript?


I am trying to implement a protected route to only allow logged in users to access my app. The code I have written seems to work, I am redirected to my login page when I try to access the homepage without being logged in, however once I am logged in I can access the page but I does not render and I get the following error: Click here for error

I have tried multiple methods and wrapping the element in my protected route seems like the V6 way of doing things, however it doesn't seem to work for me:

My protected route

interface PrivateRouteProps extends RouteProps {
}

const PrivateRoute: React.FC<PrivateRouteProps> = ({...rest}) => {
    const auth = useAuth();

    if (auth?.user === null) {
        return <Navigate to='/'/>;
    }
    return <Route {...rest}/>;
};

export default PrivateRoute;

My app (route usage)

function App() {
    useEffect(() => {
      API
        .get('api', '/reservation', {})
        .then(response => {
          console.log(response);
        })
        .catch(error => {
          console.log(error.response);
        });

    }, [])
    return (
      <Router>
        <Routes>
          <Route path='/' element={<LoginPage />}/>
          <Route path='/consultAndReserve' element={<PrivateRoute><Navbar/><ConsultReserve/></PrivateRoute>} />
          <Route path='/consultAndReserve/:date' element={<><Navbar/><ConsultReserveWithDate/></>}/>
          <Route path='/myReservations'  element={<><Navbar/><Reservations/></>}/>
          <Route path='/tracing'  element={<><Navbar/><Tracing/></>}/>
        </Routes>
      </Router>
  );
}

What am I doing wrong?


Solution

  • It's fairly trivial to create a "PrivateRoute" component, even in TypeScript.

    In your case you can't directly render a Route component as the error points out. This was a breaking change between RRDv5 and RRDv6. You can render the children prop since you are directly wrapping the components you want to protect.

    Example:

    const PrivateWrapper = ({ children }: { children: JSX.Element }) => {
      const auth = useAuth();
      return auth?.user ? children : <Navigate to="/" replace />;
    };
    

    Usage:

    <Routes>
      ...
      <Route
        path="/consoleAndReserve"
        element={(
          <PrivateWrapper>
            <Navbar />
            <ConsultReserve />
          </PrivateWrapper>
        )}
      />
      ...
    </Routes>