Waarom Routes Beveiligen?

Sommige pagina's in je app zijn alleen voor ingelogde gebruikers. Bijvoorbeeld:

  • Dashboard - alleen voor ingelogde users
  • Profile pagina - alleen voor ingelogde users
  • Settings - alleen voor ingelogde users
  • Home - voor iedereen
  • About - voor iedereen

Het probleem:

Zonder beveiliging kan iedereen gewoon /dashboard intypen in de URL en toegang krijgen!

De oplossing:

We maken een ProtectedRoute component die checkt of je ingelogd bent. Zo niet? → Redirect naar login!

ProtectedRoute Component

Maak een nieuw bestand: src/components/ProtectedRoute.jsx

import { useContext } from "react";
import { Navigate } from "react-router-dom";
import { AuthContext } from "../context/AuthContext";

function ProtectedRoute({ children }) {
  const { user } = useContext(AuthContext);

  // Als NIET ingelogd → stuur naar login
  if (!user) {
    return <Navigate to="/login" />;
  }

  // Als WEL ingelogd → toon de pagina
  return children;
}

export default ProtectedRoute;

Hoe werkt dit?

1. Check of user bestaat (= ingelogd)
2. Als niet → redirect naar /login
3. Als wel → toon de pagina (children)

Wat is children?

children is alles wat je TUSSEN de ProtectedRoute tags zet. Bijvoorbeeld:

<ProtectedRoute>
  <Dashboard />  // Dit is children!
</ProtectedRoute>

Routes Beveiligen in App.jsx

Nu gebruiken we ProtectedRoute om bepaalde routes te beveiligen:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AuthProvider } from "./context/AuthContext";
import ProtectedRoute from "./components/ProtectedRoute";

import Home from "./pages/Home";
import Register from "./pages/Register";
import Login from "./pages/Login";
import Dashboard from "./pages/Dashboard";
import Profile from "./pages/Profile";

function App() {
  return (
    <AuthProvider>
      <BrowserRouter>
        <Routes>
          {/* Publieke routes - iedereen mag hier komen */}
          <Route path="/" element={<Home />} />
          <Route path="/register" element={<Register />} />
          <Route path="/login" element={<Login />} />

          {/* Beveiligde routes - alleen voor ingelogde users */}
          <Route 
            path="/dashboard" 
            element={
              <ProtectedRoute>
                <Dashboard />
              </ProtectedRoute>
            } 
          />

          <Route 
            path="/profile" 
            element={
              <ProtectedRoute>
                <Profile />
              </ProtectedRoute>
            } 
          />
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  );
}

export default App;

Nu zijn je routes beveiligd!

Probeer maar: als je NIET ingelogd bent en naar /dashboard gaat, word je automatisch naar /login gestuurd!

Test Het

  1. Zorg dat je NIET ingelogd bent (klik logout of clear localStorage)
  2. Type in de URL: localhost:5173/dashboard
  3. Je wordt automatisch naar /login gestuurd!
  4. Log nu in
  5. Type weer: localhost:5173/dashboard
  6. Nu zie je de dashboard!

Dashboard Pagina Voorbeeld

Maak een simpele dashboard pagina: src/pages/Dashboard.jsx

import { useContext } from "react";
import { useNavigate } from "react-router-dom";
import { AuthContext } from "../context/AuthContext";

function Dashboard() {
  const { user, logout } = useContext(AuthContext);
  const navigate = useNavigate();

  const handleLogout = () => {
    logout();
    navigate("/login");
  };

  return (
    <div className="dashboard">
      <h1>Dashboard</h1>
      <p>Welkom, {user.username}! </p>
      
      <div className="dashboard-content">
        <h2>Je bent succesvol ingelogd!</h2>
        <p>Dit is een beveiligde pagina.</p>
        <p>Alleen ingelogde gebruikers kunnen dit zien.</p>
      </div>

      <button onClick={handleLogout}>
        Uitloggen
      </button>
    </div>
  );
}

export default Dashboard;

Let op: Je hoeft in Dashboard.jsx NIET meer te checken of user ingelogd is! Dat doet ProtectedRoute al voor je.

📋 Complete App.jsx

Dit is de complete App.jsx met alles erbij:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AuthProvider } from "./context/AuthContext";
import ProtectedRoute from "./components/ProtectedRoute";
import Navbar from "./components/Navbar";

// Pages
import Home from "./pages/Home";
import Register from "./pages/Register";
import Login from "./pages/Login";
import Dashboard from "./pages/Dashboard";
import Profile from "./pages/Profile";

function App() {
  return (
    <AuthProvider>
      <BrowserRouter>
        <Navbar />
        
        <Routes>
          {/* Publieke routes */}
          <Route path="/" element={<Home />} />
          <Route path="/register" element={<Register />} />
          <Route path="/login" element={<Login />} />

          {/* Beveiligde routes */}
          <Route 
            path="/dashboard" 
            element={
              <ProtectedRoute>
                <Dashboard />
              </ProtectedRoute>
            } 
          />

          <Route 
            path="/profile" 
            element={
              <ProtectedRoute>
                <Profile />
              </ProtectedRoute>
            } 
          />
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  );
}

export default App;

Extra Tips

1. Redirect naar Vorige Pagina

Als je wilt dat users terugkomen waar ze waren na inloggen:

// In ProtectedRoute.jsx
import { useLocation } from "react-router-dom";

function ProtectedRoute({ children }) {
  const { user } = useContext(AuthContext);
  const location = useLocation();

  if (!user) {
    // Sla op waar ze naartoe wilden
    return <Navigate to="/login" state={{ from: location }} />;
  }

  return children;
}

// In Login.jsx
const location = useLocation();
const from = location.state?.from?.pathname || "/dashboard";

const handleSubmit = (e) => {
  // ... login logica ...
  
  // Ga terug naar waar ze vandaan kwamen
  navigate(from);
};

2. Loading State

Als je wilt checken of AuthContext nog aan het laden is:

// In AuthContext.jsx
const [loading, setLoading] = useState(true);

useEffect(() => {
  // Check localStorage
  const savedUser = localStorage.getItem("user");
  if (savedUser) {
    setUser(JSON.parse(savedUser));
  }
  setLoading(false);
}, []);

return (
  <AuthContext.Provider value={{ user, login, logout, loading }}>
    {children}
  </AuthContext.Provider>
);

// In ProtectedRoute.jsx
const { user, loading } = useContext(AuthContext);

if (loading) {
  return <div>Laden...</div>;
}

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

return children;

3. Role-Based Access

Als je verschillende types users hebt (admin, user):

function AdminRoute({ children }) {
  const { user } = useContext(AuthContext);

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

  if (user.role !== "admin") {
    return <Navigate to="/dashboard" />;
  }

  return children;
}

// Gebruik:
<Route 
  path="/admin" 
  element={
    <AdminRoute>
      <AdminPanel />
    </AdminRoute>
  } 
/>

Checklist - Heb je alles?

  • AuthContext.jsx met login/logout/user state
  • AuthProvider om je App.jsx heen
  • ProtectedRoute.jsx component
  • ☐ Login en Register pagina's
  • ☐ Dashboard pagina (beveiligd)
  • ☐ Navbar met conditionele links
  • ☐ Routes in App.jsx met ProtectedRoute
  • ☐ localStorage voor persistente login

Je hebt nu een compleet authentication systeem in React met:
• Context API voor global state
• localStorage voor persistente login
• Protected routes voor beveiliging
• Login en register formulieren