React

React Router v7 : Routing moderne et nested routes

Découvrez comment React Router v7 révolutionne le routage moderne avec les nested routes, les loaders et la gestion avancée des erreurs.

26 Mar 2026 13 min de lecture 1 vues
1

Lectures

13

Minutes

0

Partages

Introduction

Avec plus de 2,5 millions de sites utilisant React en 2023 et une adoption en constante croissance, la gestion efficace des routes est devenue un enjeu central pour les développeurs web. React Router v7, sorti récemment, représente une évolution majeure dans l'écosystème React en proposant des fonctionnalités avancées pour gérer le routage moderne, notamment les nested routes (routes imbriquées). En 2024/2025, l'évolution rapide des applications web nécessite des solutions de routage performantes, flexibles et maintenables à grande échelle.

Cet article vous guidera à travers les principes fondamentaux de React Router v7, les avantages concrets des nested routes, comment les implémenter étape par étape dans vos projets, les stratégies avancées de chargement de données, et les erreurs courantes à éviter pour livrer des applications robustes et performantes.

Comprendre React Router v7

React Router v7 est la bibliothèque de routage de référence pour les applications React. Elle permet la navigation entre les différentes pages d'une application monopage (SPA) tout en conservant un état cohérent et une URL synchronisée avec l'interface utilisateur. En 2024, avec des applications de plus en plus complexes comportant des dizaines, voire des centaines de vues, la gestion précise et structurée des routes est devenue absolument indispensable.

Contrairement aux versions précédentes, React Router v7 adopte une approche plus déclarative et intègre nativement des concepts issus de frameworks comme Remix. Cette convergence signifie que les développeurs bénéficient désormais d'un modèle unifié pour le routage côté client et côté serveur.

Principales nouveautés de la version 7

La version 7 apporte des améliorations significatives en termes de performance, de flexibilité et d'expérience développeur. Voici les changements les plus notables :

  • Nouveau modèle de données pour les routes : les routes peuvent désormais être définies comme des objets de configuration, facilitant l'intégration des nested routes et le chargement de données.
  • Loaders et actions intégrés : inspirés de Remix, ces mécanismes permettent de charger et de muter des données directement au niveau de chaque route.
  • Gestion améliorée des erreurs : chaque route peut définir son propre composant d'erreur via errorElement, offrant une granularité fine dans la gestion des exceptions.
  • Support natif du lazy loading : les routes peuvent être chargées à la demande grâce à la propriété lazy, réduisant considérablement la taille du bundle initial.
  • Typage TypeScript renforcé : les types génériques permettent une autocomplétion et une vérification plus fiables des paramètres de route.

Installation et configuration initiale

Avant de plonger dans les nested routes, assurons-nous que votre environnement est correctement configuré. Voici comment installer React Router v7 et mettre en place une configuration de base :

# Installation de React Router v7 via npm
npm install react-router-dom@7

# Ou avec yarn
yarn add react-router-dom@7

# Ou avec pnpm
pnpm add react-router-dom@7

Une fois installé, vous pouvez configurer votre routeur principal. React Router v7 propose deux approches : la configuration déclarative classique et la configuration basée sur des objets.

// Approche déclarative classique avec React Router v7
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import NotFound from './pages/NotFound';

function App() {
  return (
    
      
        {/* Route principale */}
        } />
        {/* Pages statiques */}
        } />
        } />
        {/* Route de fallback pour les 404 */}
        } />
      
    
  );
}

export default App;
// Approche basée sur des objets avec createBrowserRouter
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import NotFound from './pages/NotFound';

// Définition des routes comme un tableau d'objets
const router = createBrowserRouter([
  {
    path: '/',
    element: ,
    errorElement: ,
  },
  {
    path: '/about',
    element: ,
  },
]);

// Utilisation de RouterProvider pour injecter le routeur
function App() {
  return ;
}

export default App;

L'approche basée sur createBrowserRouter est recommandée pour les nouveaux projets car elle donne accès à l'ensemble des fonctionnalités avancées de React Router v7, notamment les loaders et les actions.

Les nested routes : Pourquoi et comment ?

Les nested routes (routes imbriquées) permettent de structurer les applications de manière hiérarchique. Ce concept repose sur l'idée qu'une URL reflète une hiérarchie de vues : chaque segment de l'URL correspond à un composant qui s'affiche à l'intérieur de son parent. Cette approche est idéale pour les applications avec des interfaces complexes comportant des barres latérales, des onglets ou des panneaux imbriqués.

Concrètement, au lieu de redéfinir l'intégralité de la page pour chaque route, vous ne remplacez que la portion de l'interface qui change. Cela améliore considérablement la gestion de l'état, réduit les rendus inutiles et offre une navigation utilisateur plus fluide.

Le composant Outlet : la clé des nested routes

Le composant Outlet est l'élément fondamental qui rend les nested routes possibles. Il agit comme un emplacement réservé dans le composant parent où le contenu de la route enfant sera rendu dynamiquement.

// Composant parent Dashboard avec Outlet
import { Outlet, NavLink } from 'react-router-dom';

function Dashboard() {
  return (
    
{/* Navigation interne au dashboard */} {/* Zone de contenu dynamique : les routes enfants s'affichent ici */}
); } export default Dashboard;

Implémentation complète des nested routes

Pour implémenter des nested routes, il suffit de définir des routes enfants à l'intérieur d'une route parent. Voici un exemple complet avec les deux approches proposées par React Router v7 :

// Implémentation déclarative des nested routes
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './App';
import Dashboard from './pages/Dashboard';
import Profile from './pages/Profile';
import Settings from './pages/Settings';
import Analytics from './pages/Analytics';
import DashboardHome from './pages/DashboardHome';

function Root() {
  return (
    
      
        }>
          {/* Routes imbriquées dans le dashboard */}
          }>
            {/* Route index : affichée par défaut à /dashboard */}
            } />
            {/* Routes enfants : /dashboard/profile, etc. */}
            } />
            } />
            } />
          
        
      
    
  );
}
// Même configuration avec createBrowserRouter (approche recommandée)
import { createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: ,
    children: [
      {
        path: 'dashboard',
        element: ,
        children: [
          {
            index: true, // Route affichée par défaut à /dashboard
            element: ,
          },
          {
            path: 'profile',
            element: ,
          },
          {
            path: 'settings',
            element: ,
          },
          {
            path: 'analytics',
            element: ,
          },
        ],
      },
    ],
  },
]);
Conseil : Utilisez toujours une route index dans vos nested routes. Elle définit le contenu par défaut affiché lorsque l'utilisateur accède à la route parent sans spécifier de route enfant.

Chargement de données avec les loaders

L'une des fonctionnalités les plus puissantes de React Router v7 est le système de loaders. Chaque route peut définir une fonction loader qui charge les données nécessaires avant le rendu du composant. Combiné aux nested routes, ce mécanisme permet un chargement parallèle et optimisé des données à chaque niveau de la hiérarchie.

Définir un loader pour une route

Un loader est une fonction asynchrone qui retourne les données nécessaires au composant. Ces données sont ensuite accessibles via le hook useLoaderData.

// Définition d'un loader pour la route profile
import { useLoaderData } from 'react-router-dom';

// Le loader est appelé avant le rendu du composant
export async function profileLoader({ params }) {
  // Récupération des données utilisateur depuis l'API
  const response = await fetch(`/api/users/${params.userId}`);

  // Gestion des erreurs HTTP
  if (!response.ok) {
    throw new Response('Utilisateur non trouvé', { status: 404 });
  }

  return response.json();
}

// Composant Profile utilisant les données chargées
function Profile() {
  // useLoaderData retourne les données du loader
  const user = useLoaderData();

  return (
    

Profil de {user.name}

Email : {user.email}

Rôle : {user.role}

); } export default Profile;
// Intégration du loader dans la configuration des routes
import { profileLoader } from './pages/Profile';

const router = createBrowserRouter([
  {
    path: 'dashboard',
    element: ,
    children: [
      {
        path: 'profile/:userId',
        element: ,
        loader: profileLoader, // Le loader est associé à la route
        errorElement: , // Erreur spécifique à cette route
      },
    ],
  },
]);

Chargement parallèle dans les nested routes

L'un des avantages majeurs des loaders combinés aux nested routes est le chargement parallèle. Lorsqu'un utilisateur navigue vers /dashboard/profile/42, React Router v7 exécute simultanément le loader du dashboard et celui du profile. Cela élimine les cascades de requêtes (waterfalls) qui ralentissent les applications traditionnelles.

Avantages des nested routes

Les nested routes simplifient la gestion des routes complexes, réduisent le code redondant et améliorent la navigation utilisateur grâce à une hiérarchie claire. Voici un récapitulatif détaillé de leurs avantages :

FonctionnalitéAvantageImpact
Hiérarchie claireFacilite la compréhension de la structure des routesMaintenance simplifiée pour les équipes
Code réduitMoins de duplications grâce aux layouts partagésRéduction de 30 à 50 % du code de routage
Meilleure UXTransitions fluides entre vues imbriquéesNavigation instantanée sans rechargement complet
Chargement parallèleLes loaders s'exécutent simultanémentTemps de chargement réduit significativement
Gestion d'erreurs granulaireChaque route gère ses propres erreursL'application reste fonctionnelle même en cas d'erreur partielle
Lazy loading natifChargement à la demande des composantsBundle initial plus léger, meilleur score Lighthouse

Lazy loading des routes imbriquées

Pour les applications volumineuses, le lazy loading permet de ne charger le code d'une route que lorsque l'utilisateur y accède. React Router v7 simplifie cette approche avec la propriété lazy :

// Lazy loading des nested routes pour optimiser le bundle
const router = createBrowserRouter([
  {
    path: 'dashboard',
    element: ,
    children: [
      {
        path: 'analytics',
        // Le composant et son loader sont chargés à la demande
        lazy: async () => {
          const { Analytics, analyticsLoader } = await import(
            './pages/Analytics'
          );
          return {
            element: ,
            loader: analyticsLoader,
          };
        },
      },
      {
        path: 'settings',
        lazy: async () => {
          const { Settings } = await import('./pages/Settings');
          return { element:  };
        },
      },
    ],
  },
]);

Gestion avancée des erreurs

React Router v7 permet de définir des error boundaries (limites d'erreur) au niveau de chaque route. Dans un système de nested routes, cela signifie qu'une erreur dans une route enfant n'affecte pas le rendu de la route parent. L'utilisateur peut continuer à naviguer vers d'autres sections de l'application.

// Composant d'erreur personnalisé pour une route
import { useRouteError, isRouteErrorResponse } from 'react-router-dom';

function RouteErrorBoundary() {
  const error = useRouteError();

  // Vérification si l'erreur est une Response HTTP
  if (isRouteErrorResponse(error)) {
    return (
      

Erreur {error.status}

{error.statusText}

{error.status === 404 && (

La ressource demandée est introuvable.

)}
); } // Erreur inattendue return (

Une erreur inattendue est survenue

Veuillez réessayer ultérieurement.

); } export default RouteErrorBoundary;
// Utilisation de l'error boundary dans les routes imbriquées
const router = createBrowserRouter([
  {
    path: '/',
    element: ,
    errorElement: , // Erreur globale de l'application
    children: [
      {
        path: 'dashboard',
        element: ,
        errorElement: , // Erreur spécifique au dashboard
        children: [
          {
            path: 'profile/:userId',
            element: ,
            loader: profileLoader,
            // Erreur isolée : n'affecte pas le dashboard parent
            errorElement: ,
          },
        ],
      },
    ],
  },
]);

Pièges et erreurs courantes

Malgré la puissance de React Router v7, certaines erreurs reviennent fréquemment dans les projets. Voici les pièges les plus courants et comment les éviter :

  • Oublier le composant Outlet : sans Outlet dans le composant parent, les routes enfants ne seront jamais rendues. C'est l'erreur la plus fréquente chez les développeurs découvrant les nested routes.
  • Confusion entre chemins relatifs et absolus : dans les nested routes, les chemins enfants sont relatifs au parent. Écrire path="/profile" au lieu de path="profile" crée une route absolue qui ne sera pas imbriquée.
  • Absence de route index : ne pas définir de route index laisse un espace vide lorsque l'utilisateur accède à la route parent sans spécifier de sous-route.
  • Ne pas gérer les erreurs par route : sans errorElement, une erreur dans un loader fait remonter l'erreur au niveau le plus haut, potentiellement cassant toute l'application.
  • Cascades de requêtes dans les loaders : si un composant enfant attend les données du parent pour lancer sa propre requête, vous perdez l'avantage du chargement parallèle. Déplacez la logique dans les loaders pour que React Router gère la parallélisation.
  • Mauvaise gestion des redirections : utilisez la fonction redirect importée de React Router dans les loaders plutôt que de gérer les redirections dans les composants.
// Exemple de redirection correcte dans un loader
import { redirect } from 'react-router-dom';

export async function protectedLoader() {
  const user = await getAuthenticatedUser();

  // Redirection vers la page de connexion si non authentifié
  if (!user) {
    return redirect('/login');
  }

  return user;
}

Bonnes pratiques de structuration

Pour tirer le meilleur parti des nested routes dans un projet de grande envergure, voici les bonnes pratiques recommandées :

Organisation des fichiers

Adoptez une structure de fichiers qui reflète la hiérarchie de vos routes. Chaque dossier correspond à une route et contient son composant, son loader et son error boundary :

# Structure recommandée pour un projet avec nested routes
src/
├── routes/
│   ├── root.jsx           # Layout racine avec Outlet
│   ├── dashboard/
│   │   ├── index.jsx      # Route index du dashboard
│   │   ├── layout.jsx     # Layout du dashboard avec navigation et Outlet
│   │   ├── profile.jsx    # Route /dashboard/profile
│   │   ├── settings.jsx   # Route /dashboard/settings
│   │   └── analytics.jsx  # Route /dashboard/analytics
│   └── auth/
│       ├── login.jsx      # Route /auth/login
│       └── register.jsx   # Route /auth/register
├── components/            # Composants réutilisables
├── utils/                 # Fonctions utilitaires
└── main.jsx               # Point d'entrée de l'application

Centraliser la configuration des routes

Pour les projets complexes, centralisez toute la configuration des routes dans un seul fichier. Cela offre une vue d'ensemble claire et facilite les modifications :

// fichier router.js : configuration centralisée
import { createBrowserRouter } from 'react-router-dom';
import RootLayout from './routes/root';
import DashboardLayout from './routes/dashboard/layout';
import { protectedLoader } from './utils/auth';

export const router = createBrowserRouter([
  {
    path: '/',
    element: ,
    children: [
      {
        path: 'dashboard',
        element: ,
        loader: protectedLoader, // Protection de toutes les routes enfants
        children: [
          {
            index: true,
            lazy: () => import('./routes/dashboard/index'),
          },
          {
            path: 'profile/:userId',
            lazy: () => import('./routes/dashboard/profile'),
          },
          {
            path: 'settings',
            lazy: () => import('./routes/dashboard/settings'),
          },
        ],
      },
    ],
  },
]);

Conclusion

React Router v7 représente une avancée significative pour le routage dans les applications React. Grâce aux nested routes, aux loaders intégrés et à la gestion granulaire des erreurs, les développeurs disposent d'un ensemble d'outils complet pour construire des applications modernes, performantes et maintenables. L'approche basée sur createBrowserRouter combinée au lazy loading et au chargement parallèle des données élimine les problèmes de performance courants dans les applications complexes.

Voici les points clés à retenir :

  • Utilisez createBrowserRouter pour accéder à toutes les fonctionnalités de React Router v7
  • Structurez vos routes de manière hiérarchique avec les nested routes et le composant Outlet
  • Exploitez les loaders pour charger les données en parallèle et éliminer les cascades de requêtes
  • Définissez des errorElement à chaque niveau pour isoler les erreurs et maintenir l'application fonctionnelle
  • Adoptez le lazy loading pour réduire la taille du bundle initial et améliorer les performances
  • Organisez vos fichiers pour refléter la hiérarchie de vos routes

Essayez d'implémenter ces concepts dans votre prochain projet React. Commencez par migrer une section existante vers les nested routes avec des loaders, puis étendez progressivement cette approche à l'ensemble de votre application. Les gains en maintenabilité et en performance seront significatifs dès les premières itérations.

Tags

React Router Routing SPA

Partagez cet article

Twitter Facebook LinkedIn
JY
Jordane YENO

Developpeur Full Stack passionne par le web et les nouvelles technologies

En savoir plus

Articles similaires