skip to Main Content

We can restrict certain routes if the person is not logged in. However, how can we restrict certain routes for rendering if the user is logged in? Below is my routing configuration:

<BrowserRouter>
  <MenuBar />
  <Routes>
    <Route path='/' element={<PrivateRoute><Dashboard /></PrivateRoute>} />
    <Route path='/register' element={<RegisterUser />} />
    <Route path='/login' element={<LoginUser />} />
    <Route path='/profile' element={<PrivateRoute><Profile /></PrivateRoute>} />
    <Route path='/forgotpassword' element={<ForgotPassword />} />
  </Routes>
</BrowserRouter>

PrivateRoute

function PrivateRoute({ children }) {
  let user = JSON.parse(localStorage.getItem('user'));
  return (
    user ? children : < Navigate to={'/login'} />
  );
}

I do not want to refactor using modifying all the components individually. Like once User is logged in, they should not be able to go to certain screens like "/login" or "/forgotpassword" or "/register". What would be the suggested way to implement using only one PrivateRoute? Is there a more optimal implementation which I might have missed?

2

Answers


  1. You can apply the same logic as PrivateRoute .
    make a Component <AuthRoute> and wrap your pages with it, if the use is authenticated redirect t "/". something like :

    function AuthRoute({ children }) {
    let user = JSON.parse(localStorage.getItem('user'));
    return (
        !user ? children : < Navigate to={'/'} />
           );
    }
    

    another advice instead of wrapping each component with <PrivateRoute> or <AuthRoute> you can nest them in Route which take <PrivateRoute> as it’ element :

    <Route path='/' element={<PrivateRoute />}>
      <Route  index element={<Dashboard  />} />
      <Route path='/profile' element={<Profile /> }
    </Route>} />
    

    and replace children in PrivateRoute with <Outlet/>

    Login or Signup to reply.
  2. For separation of concerns you really should create a separate component for protecting unauthenticated routes. It uses the same logic as the PrivateRoute but inverts the condition.

    Example:

    function PrivateRoute () {
      const user = JSON.parse(localStorage.getItem('user'));
      return user ? <Outlet /> : <Navigate to="/login" replace />;
    }
    
    function AnonymousRoute () {
      const user = JSON.parse(localStorage.getItem('user'));
      return user ? <Navigate to="/" replace /> : <Outlet />;
    }
    
    <BrowserRouter>
      <MenuBar />
      <Routes>
        <Route element={<PrivateRoute />}>
          <Route path='/' element={<Dashboard />} />
          <Route path='/profile' element={<Profile />} />
        </Route>
        <Route element={<AnonymousRoute />}>
          <Route path='/register' element={<RegisterUser />} />
          <Route path='/login' element={<LoginUser />} />
          <Route path='/forgotpassword' element={<ForgotPassword />} />
        </Route>
      </Routes>
    </BrowserRouter>
    

    If you insist on only updating the PrivateRoute component to do double-duty then I’d suggest this refactor to consume an auth condition and target route path for redirection.

    Example:

    function ProtectedRoute ({ isAuth, target }) {
      const user = JSON.parse(localStorage.getItem('user'));
    
      if (isAuth) {
        return user ? <Outlet /> : <Navigate to={target} replace />;
      }
      return user ? <Navigate to={target} replace /> : <Outlet />;
    }
    
    <BrowserRouter>
      <MenuBar />
      <Routes>
        <Route element={<ProtectedRoute isAuth target="/login" />}>
          <Route path='/' element={<Dashboard />} />
          <Route path='/profile' element={<Profile />} />
        </Route>
        <Route element={<ProtectedRoute target="/" />}>
          <Route path='/register' element={<RegisterUser />} />
          <Route path='/login' element={<LoginUser />} />
          <Route path='/forgotpassword' element={<ForgotPassword />} />
        </Route>
      </Routes>
    </BrowserRouter>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search