When building full-stack applications with user accounts, you need a bulletproof way to stop logged-out visitors from accessing private dashboards. Relying on backend API checks alone leads to a clunky user experience where the page loads, fails, and then aggressively kicks the user out.
You need a frontend gatekeeper. This clean React Protected Route component instantly checks a user’s authentication status and redirects them to the login page before the private component even tries to render.
The Protected Route Component
This snippet is designed for React Router v6. It uses the Navigate component to handle the redirect and the Outlet component to render whatever private page the user is trying to reach.
import { Navigate, Outlet } from 'react';
const ProtectedRoute = ({ isAuthenticated, redirectPath = '/login' }) => {
if (!isAuthenticated) {
// If the user is not logged in, send them to the login page
// The "replace" prop prevents them from using the browser's back button to bypass the lock
return <Navigate to={redirectPath} replace />;
}
// If they are logged in, render the child route components
return <Outlet />;
};
export default ProtectedRoute;
How to Use It
To implement this, wrap your private routes inside this component in your main App.jsx or routing file. You can pass your actual authentication state (whether from Context, Redux, or a custom hook) directly into the isAuthenticated prop.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import ProtectedRoute from './ProtectedRoute';
// Import your pages
import Home from './Home';
import Login from './Login';
import Dashboard from './Dashboard';
import Settings from './Settings';
function App() {
// Replace this boolean with your actual global auth state
const userIsLoggedIn = false;
return (
<BrowserRouter>
<Routes>
{/* Public Routes */}
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
{/* Private Protected Routes */}
<Route element={<ProtectedRoute isAuthenticated={userIsLoggedIn} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;