Bases du Routing
Maintenant que vous comprenez pourquoi le routing est nécessaire, voyons comment l'implémenter avec React Router.
Setup Initial
1. Installer React Router
npm install react-router-dom
React Router DOM
Il existe plusieurs versions de React Router :
- react-router-dom → Pour le web (navigateur)
- react-router-native → Pour React Native (mobile)
Nous utilisons react-router-dom !
Version
Ce cours utilise React Router v6.
Si vous lisez des tutoriels plus anciens avec <Switch> ou component=, ils utilisent v5 (obsolète).
2. Envelopper l'App avec BrowserRouter
// main.jsx ou index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
Où mettre BrowserRouter ?
Option 1 : Dans main.jsx (recommandé)
<BrowserRouter>
<App />
</BrowserRouter>
Option 2 : Dans App.jsx
function App() {
return (
<BrowserRouter>
{/* Routes */}
</BrowserRouter>
);
}
Les deux fonctionnent. Option 1 sépare la config du routing de l'app.
BrowserRouter vs HashRouter
BrowserRouter (recommandé)
- URLs sans
#:/about,/products/123 - Nécessite configuration serveur en production
HashRouter
- URLs avec
#:/#/about,/#/products/123 - Fonctionne sans config serveur
Utilisez BrowserRouter sauf contrainte spécifique !
Définir des Routes
Routes Simples
// App.jsx
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
);
}
export default App;
Syntaxe Route
<Route path="/url" element={<Component />} />
- path : L'URL qui active cette route
- element : Le composant à afficher
Important : element prend un élément JSX, pas un composant !
// ✅ Bon
<Route path="/" element={<Home />} />
// ❌ Mauvais
<Route path="/" element={Home} />
<Route path="/" component={Home} /> // v5 syntax, obsolète
Quelle est la bonne syntaxe pour définir une route en React Router v6 ?
Index Route
Pour la page d'accueil, vous pouvez utiliser path="/" ou index :
<Routes>
<Route path="/" element={<Layout />}>
{/* Ces deux sont équivalents pour la page d'accueil */}
<Route path="/" element={<Home />} />
{/* OU */}
<Route index element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
Navigation avec Link
Pour créer des liens entre pages, utilisez <Link>.
import { Link } from 'react-router-dom';
function Navigation() {
return (
<nav>
<ul>
<li>
<Link to="/">Accueil</Link>
</li>
<li>
<Link to="/about">À propos</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
);
}
Link vs <a>
Utilisez toujours <Link> pour la navigation interne !
// ❌ Recharge la page
<a href="/about">About</a>
// ✅ Navigation SPA (sans rechargement)
<Link to="/about">About</Link>
// ✅ Pour les liens externes, utilisez <a>
<a href="https://google.com" target="_blank">Google</a>
NavLink : Link avec Style Actif
NavLink est comme Link, mais avec un style automatique pour le lien actif.
import { NavLink } from 'react-router-dom';
function Navigation() {
return (
<nav>
<NavLink
to="/"
className={({ isActive }) => (isActive ? 'active' : '')}
>
Home
</NavLink>
<NavLink
to="/about"
className={({ isActive }) => (isActive ? 'active' : '')}
>
About
</NavLink>
</nav>
);
}
// CSS
// .active { color: blue; font-weight: bold; }
Avec style inline :
<NavLink
to="/about"
style={({ isActive }) => ({
color: isActive ? 'blue' : 'black',
fontWeight: isActive ? 'bold' : 'normal'
})}
>
About
</NavLink>
Quand utiliser NavLink ?
NavLink : Pour la navigation principale où vous voulez montrer la page active
Link : Pour tous les autres liens
// Navigation principale → NavLink
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
</nav>
// Liens dans le contenu → Link
<p>
Voir notre <Link to="/blog">blog</Link> pour plus d'infos.
</p>
Quelle est la différence entre Link et NavLink ?
Navigation Programmatique
Parfois, vous devez naviguer depuis du code JavaScript (pas un clic de lien).
useNavigate Hook
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
const [username, setUsername] = useState('');
function handleSubmit(e) {
e.preventDefault();
// Faire la validation...
if (username) {
// Rediriger vers le dashboard
navigate('/dashboard');
}
}
return (
<form onSubmit={handleSubmit}>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<button type="submit">Se connecter</button>
</form>
);
}
Cas d'Usage de navigate()
const navigate = useNavigate();
// Naviguer vers une URL
navigate('/products');
// Naviguer en arrière (comme le bouton retour)
navigate(-1);
// Naviguer en avant
navigate(1);
// Remplacer l'historique (pas de bouton retour possible)
navigate('/login', { replace: true });
// Passer des données à la page suivante
navigate('/profile', { state: { from: 'login' } });
navigate vs Link
<Link> : Pour les liens cliquables (UI)
<Link to="/about">About</Link>
navigate() : Pour la navigation programmatique (logique)
// Après une action
handleSubmit() {
// ... validation
navigate('/success');
}
// Redirection conditionnelle
if (!isLoggedIn) {
navigate('/login');
}
Quand utiliser navigate() plutôt que <Link> ?
Layouts & Routes Imbriquées
Pour partager un layout commun entre plusieurs routes.
Sans Layouts (Répétitif)
// ❌ Répétition du Header et Footer
function Home() {
return (
<div>
<Header />
<main>Page d'accueil</main>
<Footer />
</div>
);
}
function About() {
return (
<div>
<Header />
<main>À propos</main>
<Footer />
</div>
);
}
Avec Layouts (DRY)
import { Outlet } from 'react-router-dom';
// Layout commun
function Layout() {
return (
<div>
<Header />
<main>
<Outlet /> {/* Le contenu de la route enfant s'affiche ici */}
</main>
<Footer />
</div>
);
}
// Pages (sans Header/Footer)
function Home() {
return <h1>Page d'accueil</h1>;
}
function About() {
return <h1>À propos</h1>;
}
// Routes
function App() {
return (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
</Route>
</Routes>
);
}
Résultat :
/ → Layout (Header + Home + Footer)
/about → Layout (Header + About + Footer)
/contact → Layout (Header + Contact + Footer)
Outlet
<Outlet /> est un placeholder pour les routes enfants.
function Layout() {
return (
<div>
<Header />
<Outlet /> {/* Ici s'affiche <Home />, <About />, etc. */}
<Footer />
</div>
);
}
C'est l'équivalent de {children} mais pour le routing !
Que fait <Outlet /> dans un composant Layout ?
Page 404 (Not Found)
Gérer les URLs invalides avec une route "catch-all".
function NotFound() {
return (
<div>
<h1>404 - Page non trouvée</h1>
<p>La page que vous cherchez n'existe pas.</p>
<Link to="/">Retour à l'accueil</Link>
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* Route catch-all : doit être en dernier */}
<Route path="*" element={<NotFound />} />
</Routes>
);
}
path=*
path="*" match n'importe quelle URL qui ne correspond pas aux routes précédentes.
Important : Mettez-la toujours en dernier !
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} /> {/* En dernier */}
</Routes>
Exemple Complet
// App.jsx
import { Routes, Route, Link } from 'react-router-dom';
import { Outlet } from 'react-router-dom';
// Layout
function Layout() {
return (
<div>
<header>
<h1>Mon Site</h1>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/blog">Blog</Link>
<Link to="/contact">Contact</Link>
</nav>
</header>
<main>
<Outlet />
</main>
<footer>
<p>© 2025 Mon Site</p>
</footer>
</div>
);
}
// Pages
function Home() {
return <h2>Bienvenue !</h2>;
}
function About() {
return <h2>À propos de nous</h2>;
}
function Blog() {
return <h2>Blog</h2>;
}
function Contact() {
const navigate = useNavigate();
function handleSubmit(e) {
e.preventDefault();
// ... envoyer le message
navigate('/'); // Rediriger vers home
}
return (
<div>
<h2>Contactez-nous</h2>
<form onSubmit={handleSubmit}>
<input type="email" placeholder="Email" />
<textarea placeholder="Message" />
<button type="submit">Envoyer</button>
</form>
</div>
);
}
function NotFound() {
return (
<div>
<h2>404 - Page non trouvée</h2>
<Link to="/">Retour à l'accueil</Link>
</div>
);
}
// App
function App() {
return (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="blog" element={<Blog />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
);
}
export default App;
Organisation des Fichiers
src/
├── pages/
│ ├── Home.jsx
│ ├── About.jsx
│ ├── Blog.jsx
│ ├── Contact.jsx
│ └── NotFound.jsx
├── components/
│ ├── Layout.jsx
│ ├── Header.jsx
│ ├── Footer.jsx
│ └── Navigation.jsx
├── App.jsx
└── main.jsx
Convention
pages/ : Composants qui sont des "pages" (une par route)
components/ : Composants réutilisables (Header, Button, Card, etc.)
layouts/ : Layouts communs (MainLayout, AdminLayout, etc.)
Récapitulatif
Comprendre, pas mémoriser
Ce qu'il faut retenir :
<Route path="/about" element={<About />} />→ définir une route<Link to="/about">→ naviguer entre pages (pas<a>)<NavLink>→ liens avec style actif (navigation principale)navigate()→ navigation programmatique (après un submit, etc.)<Outlet />→ placeholder pour les routes enfants (layouts)path="*"→ route catch-all pour la page 404 (toujours en dernier)
Avec la pratique, cette structure deviendra naturelle. Consultez la documentation React Router si vous avez un doute.
Prochaine Étape
Maintenant que vous maîtrisez les bases du routing, découvrons les routes dynamiques avec paramètres d'URL !