skip to Main Content

I am using react-router-dom for Routing in my react app. I now want to create a protected route so you can access certain pages only if you are logged in. But at the moment I can still access the protected pages and dont get redirected from the login page to the dashboard after loggin in

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import {
    BrowserRouter as Router,
    Routes,
    Route,
    Navigate,
} from 'react-router-dom';
import axios from 'axios';
import { UserContextProvider } from './context/userContext';
import { ToastProvider } from './context/toastContext';
import { DialogProvider } from './context/dialogContext';
import ProtectedRoute from './components/protectedRoute';
import Register from './pages/auth/register';
import Profile from './pages/profile';
import Friends from './pages/friends';
import Notifications from './pages/notifications';
import Landingpage from './pages/landingpage';
import Dashboard from './pages/dashboard';
import Login from './pages/auth/login';
import './index.css';

const routes = [
    { path: '/home', element: Landingpage },
    { path: '/dashboard', element: Dashboard, protected: true },
    { path: '/login', element: Login },
    { path: '/register', element: Register },
    { path: '/profile', element: Profile, protected: true },
    { path: '/friends', element: Friends, protected: true },
    { path: '/notifications', element: Notifications, protected: true },
    { path: '/', element: Navigate, to: '/home' },
];

axios.defaults.baseURL = 'http://localhost:8000';
axios.defaults.withCredentials = true;

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <UserContextProvider>
        <ToastProvider>
            <DialogProvider>
                <Router>
                    <Routes>
                        {routes.map((route, index) => {
                            if (route.protected) {
                                return (
                                    <Route
                                        key={index}
                                        path={route.path}
                                        element={
                                            <ProtectedRoute
                                                element={route.element}
                                            />
                                        }
                                    />
                                );
                            }
                            return (
                                <Route
                                    key={index}
                                    path={route.path}
                                    element={<route.element to={route.to} />}
                                />
                            );
                        })}
                    </Routes>
                </Router>
            </DialogProvider>
        </ToastProvider>
    </UserContextProvider>
);

protectedRoute.jsx

import React, { useContext } from 'react';
import { Navigate } from 'react-router-dom';
import { UserContext } from '../context/userContext';
import { Loader } from 'lucide-react';

const ProtectedRoute = ({ element: Component, ...rest }) => {
    const { user, loading } = useContext(UserContext);

    if (loading) {
        return (
            <div className='flex items-center justify-center py-4'>
                <Loader className='animate-spin mr-2' />
                <span>Lädt...</span>
            </div>
        );
    }

    if (!user) {
        return <Navigate to='/login' />;
    }

    return <Component {...rest} />;
};

export default ProtectedRoute;

2

Answers


  1. You can use it like this way.

    // App.tsx
    import { BrowserRouter, Route, Routes } from "react-router-dom";
    import Dashboard from "./pages/system/Dashboard";
    import User from "./pages/system/users/User";
    import Layout from "./layout/DashboardLayout";
    import Expence from "./pages/system/expenses/Expense";
    import Product from "./pages/manager/Product";
    import NotFound from "./pages/common/NotFound";
    import PersistLogin from "./access/PersistLogin";
    import ProtectedRoutes from "./access/ProtectedRoutes";
    import { UserRole } from "./utils";
    
    function App() {
      return (
        <BrowserRouter future={{ v7_startTransition: true }} basename="/">
          <Routes>
            {/* ======Protected routes====== */}
            <Route element={<PersistLogin />}>
              <Route
                element={
                  <ProtectedRoutes
                    allowedRoles={[UserRole.SYSTEM_ADMIN, UserRole.MANAGER]}
                    redirectTo="/auth"
                  />
                }
              >
                <Route path="/admin" element={<Layout />}>
                  <Route path="dashboard" element={<Dashboard />} />
                  <Route path="users" element={<User />} />
                  <Route path="products" element={<Product />} />
                  <Route path="expenses" element={<Expense />} />
                </Route>
              </Route>
            </Route>
            {/* ======Protected routes====== */}
    
            {/* ======Invalid / Catch-all route for 404====== */}
            <Route path="*" element={<NotFound />} />
          </Routes>
        </BrowserRouter>
      );
    }
    
    export default App;
    

    The interesting fact is currently I’m exploring this routing system 🐸

    Here is the ProtectedRoutes.tsx file code.

    // ProtectedRoutes.tsx
    import { TUserRole } from "@/@types";
    import useAuth from "@/hooks/auth/useAuth";
    import { Navigate, Outlet } from "react-router-dom";
    
    type ProtectedRoutes = {
      allowedRoles: Array<TUserRole>;
      redirectTo: string;
    };
    
    const ProtectedRoutes = ({ allowedRoles, redirectTo }: ProtectedRoutes) => {
      const { session } = useAuth();
      // Check if user is logged in and has valid roles
      if (session?.accessToken) {
        if (allowedRoles.includes(session.user.role)) {
          return <Outlet />;
        }
        // window.location.replace("/");
        return <Navigate to="/" />;
      }
      return <Navigate to={redirectTo} />;
    };
    
    export default ProtectedRoutes;
    
    Login or Signup to reply.
  2. One way you can do it, is, first store the user in localStorage

    localStorage.setItem("userProfile", JSON.stringify(user))

    and than get it in the index.js file

    const user = JSON.parse(localStorage.getItem("userProfile"))

    and check it in the Route itself that whether the user exists or not. If not, Navigate them to login page

    <Route
      key={index}
      path={route.path}
      element={!user ? 
       <Navigate replace to="/login" /> :
       <ProtectedRoute
       element={route.element}
       />
      }
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search