Restricted and Private routes in React

Let us see how can we create restricted and private routes in React with react-router-dom-v6.

Working with routes on the client-side can be challenging as route states are managed with browser history objects.

But with react-router-dom (v6), one of the most used route-management-library for React, makes it extremely easy to manage routes.

In v6 the paths are wrapped under the Routes component to make it work, Route can be nested and this is what makes it easy to use.

<Routes>
  <Route path="/" element={<RestrictedRoutes />}>
   <Route path="login" element={<Login />} />
   <Route path="forgot-password" element={<ForgotPassword />} />
   <Route path="reset-password" element={<ResetPassword {...props} />} />
  </Route>
</Routes>

At the / path it will render the RestrictedRoutes, consider it as parent component and under that if the path is /login that is / + login it will render Login component.

Thus we can have our logic inside the RestrictedRoutes.

In this RestrictedRoutes component, if the user is logged in it will redirect to the homepage otherwise it will render the child component using Outlet.

import React from 'react';
import { Outlet, Navigate } from 'react-router-dom';
import { useStore } from '../App/authStore';

const RestrictedRoutes = (): JSX.Element => {
  const isLoggedIn = useStore((state) => state.isLoggedIn);
  return !isLoggedIn ? <Outlet /> : <Navigate to="/home" />;
};

export default RestrictedRoutes;

The Navigate object provided by react-router-dom is used for redirection and the Outlet is used to render child components under the given route, that matches the current path.

In the same way, we can have another component say ProtectedRoutes, that will force users to login page if they are not logged in.

import React from 'react';
import { Outlet, Navigate } from 'react-router-dom';
import { useStore } from '../App/authStore';

const PrivateRoutes = (): JSX.Element => {
  const isLoggedIn = useStore((state) => state.isLoggedIn);
  return isLoggedIn ? <Outlet /> : <Navigate to="/login" />;
};

export default PrivateRoutes;

The great thing about React is we can multiple routes with different restrictions and they will render accordingly.

<Routes>
  <Route path="/" element={<RestrictedRoutes />}>
    <Route path="login" element={<Login />} />
    <Route path="forgot-password" element={<ForgotPassword />} />
    <Route path="reset-password" element={<ResetPassword {...props} />} />
  </Route>
  <Route path="/" element={<PrivateRoutes />}>
    <Route path="home" element={<Home />} />
    <Route path="settings" element={<Settings />} />
    <Route path="about-us" element={<AboutUs {...props} />} />
  </Route>
</Routes>