Learn to implement protected routes in your React application. We'll show you how to guard dashboard pages and redirect unauthenticated users securely.
Previously in this course, we covered Introduction to React Router: Building Multi-Page SPAs and established a robust way of Handling Authentication State with React Context API. Now, we need to bridge these two concepts.
Even if your UI hides navigation links for logged-out users, a determined user can still type a URL directly into their browser to reach a private dashboard. To ensure real security, we need to implement protected routes—a pattern that acts as a gatekeeper for your component tree.
From first principles, a protected route is simply a higher-order wrapper component. Instead of rendering your private components (like Dashboard or Settings) directly in your router configuration, you pass them through a "guard" component that checks the authentication state.
If the user is authenticated, the guard renders the requested page. If not, it redirects the user to the login screen.
We will create a ProtectedRoute component that consumes our AuthContext. This component will leverage the Navigate component provided by react-router-dom to handle the redirect logic.
JSXimport { Navigate, useLocation } from CE9178">'react-router-dom'; import { useAuth } from CE9178">'./AuthProvider'; // Our custom hook from previous lessons const ProtectedRoute = ({ children }) => { const { isAuthenticated, isLoading } = useAuth(); const location = useLocation(); // 1. Handle loading state to prevent flickering if (isLoading) { return <div>Loading authentication...</div>; } // 2. Redirect if not authenticated if (!isAuthenticated) { // We pass the current location so we can redirect back after login return <Navigate to="/login" state={{ from: location }} replace />; } // 3. Render the child component if authenticated return children; };
Now that we have our guard, we integrate it into our main routing configuration. Following the principles from Nested Routes and Layouts: Mastering React Router UI Design, we can wrap entire sections of our app.
JSXimport { BrowserRouter, Routes, Route } from CE9178">'react-router-dom'; function App() { return ( <BrowserRouter> <Routes> <Route path="/login" element={<Login />} /> {/* Protected routes wrapped in the guard */} <Route path="/dashboard/*" element={ <ProtectedRoute> <DashboardLayout /> </ProtectedRoute> } /> </Routes> </BrowserRouter> ); }
ProtectedRoute.jsx.ProtectedRoute component shown above.App.js router to wrap your Dashboard route with this component./dashboard/settings, and verify that you are redirected to /login.AuthContext checks a server or local storage asynchronously, the isAuthenticated flag might be false for a split second on page load. If you don't check for an isLoading state, your app will flicker and redirect users to the login page even when they are properly signed in.Login route is not wrapped in a ProtectedRoute. If it is, the app will try to redirect the login page to the login page, creating an infinite loop.By implementing these protected routes, you prevent unauthorized access to your dashboard views and ensure a consistent, secure flow for your users. This pattern is the standard way to handle private areas in a React single-page application.
Up next, we will explore Programmatic Navigation to handle redirects after login and logout events.
Learn to manage authentication state in React using the Context API. Build a secure, scalable AuthProvider to track login status and handle user sessions.
Read moreLearn to create custom hooks in React to abstract complex data-fetching logic. Improve your code reusability and simplify your components by building a useFetch.
Protected Routes for Authenticated Views
Asynchronous Data Lifecycle
Caching Strategies with React Query
Mutations and Data Updates
Synchronizing Client and Server State
Integrating Live Data into the Dashboard
Error Handling and Loading UI
Controlled vs Uncontrolled Components
Real-time Form Validation
Schema-based Validation with Zod
Handling Multi-step Forms
Optimizing Form Submissions
Performance Profiling with React DevTools
Refactoring for Scalability
Finalizing Dashboard Data Flow
Deploying the Application
Advanced Hook Composition
Implementing Middleware for State
Advanced Context Patterns
Router Loaders and Data Prefetching
Complex Route Guards
Handling Large Datasets in UI
Testing Hooks and Components
Managing Global Modals
Implementing Keyboard Shortcuts
Optimizing Asset Loading
Internationalization Basics
Managing WebSocket Connections