Skip to main content

Protected Routes

A wrapper component that redirects unauthenticated users to the login page.

ProtectedRoute Component

src/components/ProtectedRoute.tsx
import { type ReactNode } from 'react';
import { Navigate } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';

export function ProtectedRoute({ children }: { children: ReactNode }) {
const { isAuthenticated, isLoading } = useAuth();

if (isLoading) {
return (
<div className="auth-layout">
<div className="spinner" />
</div>
);
}

if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}

return <>{children}</>;
}

Usage

Wrap any route that requires authentication:

src/App.tsx
<Route
path="/dashboard"
element={
<ProtectedRoute>
<DashboardPage />
</ProtectedRoute>
}
/>
<Route
path="/profile"
element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}
/>

With Return URL

To redirect back to the protected page after login:

src/components/ProtectedRoute.tsx
import { type ReactNode } from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';

export function ProtectedRoute({ children }: { children: ReactNode }) {
const { isAuthenticated, isLoading } = useAuth();
const location = useLocation();

if (isLoading) {
return <div className="spinner" />;
}

if (!isAuthenticated) {
return <Navigate to="/login" state={{ from: location }} replace />;
}

return <>{children}</>;
}

Then in the login page, redirect back after successful authentication:

src/pages/LoginPage.tsx
const location = useLocation();
const from = (location.state as { from?: Location })?.from?.pathname || '/dashboard';

// After successful login:
navigate(from, { replace: true });