🗺️ Introduction au routing côté client
React Router permet de créer des Single Page Applications (SPA) avec plusieurs "pages" sans rechargement du navigateur. L'URL change, mais React re-rend simplement les composants correspondants.
Dans ce module, les exemples montrent la syntaxe React Router v6 (la version actuelle). En production, installez
react-router-dom via npm. Pour les mini-projets CDN, nous simulons le routing avec du state.⚙️ Installation et configuration
# Installation
npm install react-router-dom
# Structure recommandée
src/
pages/
Home.jsx
About.jsx
Profile.jsx
NotFound.jsx
components/
Navbar.jsx
App.jsx
main.jsx
// main.jsx — BrowserRouter englobe tout
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
🛣️ Routes de base
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import NotFound from './pages/NotFound';
function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserDetail />} />
<Route path="*" element={<NotFound />} /> {/* catch-all */}
</Routes>
</div>
);
}
// Routes imbriquées (nested routes)
function App() {
return (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="blog">
<Route index element={<BlogList />} />
<Route path=":slug" element={<BlogPost />} />
</Route>
</Route>
</Routes>
);
}
// Layout avec Outlet (emplacement des routes enfants)
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<div>
<Navbar />
<main>
<Outlet /> {/* les routes enfants s'affichent ici */}
</main>
</div>
);
}
🔢 Paramètres URL et Query String
import { useParams, useSearchParams, useLocation } from 'react-router-dom';
// useParams — paramètres dynamiques (/users/:id)
function UserDetail() {
const { id } = useParams();
// URL /users/42 → id = "42"
return <p>Profil utilisateur #{id}</p>;
}
// useSearchParams — query string (?page=2&sort=date)
function BlogList() {
const [searchParams, setSearchParams] = useSearchParams();
const page = parseInt(searchParams.get('page') || '1');
const sort = searchParams.get('sort') || 'date';
function nextPage() {
setSearchParams({ page: page + 1, sort });
}
return (
<div>
<p>Page {page} — Tri : {sort}</p>
<button onClick={nextPage}>Page suivante</button>
</div>
);
}
// useLocation — infos sur l'URL actuelle
function Page() {
const location = useLocation();
// location.pathname, location.search, location.hash, location.state
return <p>Route actuelle : {location.pathname}</p>;
}
🔒 Routes protégées
import { Navigate, Outlet } from 'react-router-dom';
// Composant de protection
function RequireAuth({ children }) {
const { user } = useAuth();
if (!user) {
return <Navigate to="/login" replace />;
}
return children;
}
// Ou avec Outlet pour les routes imbriquées
function ProtectedLayout() {
const { user } = useAuth();
if (!user) return <Navigate to="/login" replace />;
return <Outlet />;
}
// Usage dans App
function App() {
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedLayout />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
</Route>
</Routes>
);
}