Français

Explorez les modèles de navigation essentiels avec React Router v6. Apprenez le routage déclaratif, les routes dynamiques, la navigation programmatique, les routes imbriquées et les stratégies de chargement de données pour créer des applications web robustes et conviviales.

React Router v6 : Maîtriser les Modèles de Navigation pour les Applications Web Modernes

React Router v6 est une bibliothèque de routage puissante et flexible pour les applications React. Elle vous permet de créer des applications monopages (SPA) avec une expérience utilisateur fluide en gérant la navigation sans rechargement complet de la page. Cet article de blog explorera les modèles de navigation essentiels utilisant React Router v6, vous fournissant les connaissances et les exemples pour construire des applications web robustes et conviviales.

Comprendre les Concepts Fondamentaux de React Router v6

Avant de plonger dans des modèles spécifiques, passons en revue quelques concepts fondamentaux :

1. Routage Déclaratif avec <Routes> et <Route>

Le fondement de React Router v6 repose sur le routage déclaratif. Vous définissez vos routes en utilisant les composants <Routes> et <Route>. Le composant <Routes> agit comme un conteneur pour vos routes, et le composant <Route> définit une route spécifique et le composant à rendre lorsque cette route correspond à l'URL actuelle.

Exemple : Configuration de base des routes

Voici un exemple de base de configuration de routes pour une application simple :


import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  return (
    
      
        } />
        } />
        } />
      
    
  );
}

export default App;

Dans cet exemple, nous définissons trois routes :

Le composant BrowserRouter active le routage basé sur l'historique du navigateur. React Router compare l'URL actuelle avec les routes définies et rend le composant correspondant.

2. Routes Dynamiques avec Paramètres d'URL

Les routes dynamiques vous permettent de créer des routes qui peuvent gérer différentes valeurs dans l'URL. Ceci est utile pour afficher du contenu basé sur un identifiant unique, comme un ID de produit ou un ID d'utilisateur. React Router v6 utilise le symbole : pour définir les paramètres d'URL.

Exemple : Affichage des détails d'un produit

Imaginons que vous ayez une application de e-commerce et que vous souhaitiez afficher les détails de chaque produit en fonction de son ID. Vous pouvez définir une route dynamique comme ceci :


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Récupérer les détails du produit en fonction du productId
  // ...

  return (
    

Détails du Produit

ID du Produit : {productId}

{/* Afficher les détails du produit ici */}
); } function App() { return ( } /> ); } export default App;

Dans cet exemple :

Exemple d'Internationalisation : Gestion des Codes de Langue

Pour un site web multilingue, vous pourriez utiliser une route dynamique pour gérer les codes de langue :


} />

Cette route correspondrait à des URL comme /en/about, /fr/about, et /es/about. Le paramètre lang peut ensuite être utilisé pour charger les ressources linguistiques appropriées.

3. Navigation Programmatique avec useNavigate

Bien que le routage déclaratif soit excellent pour les liens statiques, vous avez souvent besoin de naviguer de manière programmatique en fonction des actions de l'utilisateur ou de la logique de l'application. React Router v6 fournit le hook useNavigate à cet effet. useNavigate renvoie une fonction qui vous permet de naviguer vers différentes routes.

Exemple : Redirection après la soumission d'un formulaire

Supposons que vous ayez une soumission de formulaire et que vous souhaitiez rediriger l'utilisateur vers une page de succès après que le formulaire a été soumis avec succès :


import { useNavigate } from "react-router-dom";

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Soumettre les données du formulaire
    // ...

    // Rediriger vers la page de succès après une soumission réussie
    navigate("/success");
  };

  return (
    
{/* Champs du formulaire */}
); } export default MyForm;

Dans cet exemple :

Passer un état (state) pendant la navigation

Vous pouvez également passer un état avec la navigation en utilisant le deuxième argument de navigate :


navigate("/confirmation", { state: { orderId: "12345" } });

Cela vous permet de passer des données au composant cible, qui peuvent être accédées en utilisant le hook useLocation.

4. Routes Imbriquées et Mises en Page (Layouts)

Les routes imbriquées vous permettent de créer des structures de routage hiérarchiques, où une route est imbriquée dans une autre. Ceci est utile pour organiser des applications complexes avec plusieurs niveaux de navigation. Cela aide à créer des mises en page où certains éléments de l'interface utilisateur sont présents de manière cohérente dans une section de l'application.

Exemple : Section du profil utilisateur

Imaginons que vous ayez une section de profil utilisateur avec des routes imbriquées pour afficher les informations du profil, les paramètres et les commandes de l'utilisateur :


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

Profil Utilisateur

  • Informations du Profil
  • Paramètres
  • Commandes
} /> } /> } />
); } function ProfileInformation() { return

Composant des Informations du Profil

; } function Settings() { return

Composant des Paramètres

; } function Orders() { return

Composant des Commandes

; } function App() { return ( } /> ); } export default App;

Dans cet exemple :

Le caractère * dans la route parente est crucial ; il signifie que la route parente doit correspondre à n'importe quel sous-chemin, permettant aux routes imbriquées d'être correctement associées à l'intérieur du composant Profile.

5. Gestion des Erreurs "Non Trouvé" (404)

Il est essentiel de gérer les cas où l'utilisateur navigue vers une route qui n'existe pas. React Router v6 facilite cela avec une route fourre-tout (catch-all).

Exemple : Implémentation d'une page 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - Non Trouvé

La page que vous recherchez n'existe pas.

Retour à l'accueil
); } function App() { return ( } /> } /> } /> ); }

Dans cet exemple :

6. Stratégies de Chargement de Données avec React Router v6

React Router v6 n'inclut pas de mécanismes de chargement de données intégrés comme son prédécesseur (React Router v5 avec `useRouteMatch`). Cependant, il fournit les outils pour implémenter efficacement diverses stratégies de chargement de données.

Option 1 : Récupérer les données dans les composants

L'approche la plus simple consiste à récupérer les données directement dans le composant qui rend la route. Vous pouvez utiliser le hook useEffect pour récupérer les données lorsque le composant se monte ou lorsque les paramètres de l'URL changent.


import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";

function ProductDetails() {
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProduct() {
      try {
        const response = await fetch(`/api/products/${productId}`);
        if (!response.ok) {
          throw new Error(`Erreur HTTP ! statut : ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Chargement...

; if (error) return

Erreur : {error.message}

; if (!product) return

Produit non trouvé

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Cette approche est simple mais peut entraîner une duplication de code si vous devez récupérer des données dans plusieurs composants. Elle est également moins efficace car la récupération des données ne commence qu'après le montage du composant.

Option 2 : Utiliser un hook personnalisé pour la récupération de données

Pour réduire la duplication de code, vous pouvez créer un hook personnalisé qui encapsule la logique de récupération des données. Ce hook peut ensuite être réutilisé dans plusieurs composants.


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`Erreur HTTP ! statut : ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Ensuite, vous pouvez utiliser ce hook dans vos composants :


import { useParams } from "react-router-dom";
import useFetch from "./useFetch";

function ProductDetails() {
  const { productId } = useParams();
  const { data: product, loading, error } = useFetch(`/api/products/${productId}`);

  if (loading) return 

Chargement...

; if (error) return

Erreur : {error.message}

; if (!product) return

Produit non trouvé

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Option 3 : Utiliser une bibliothèque de routage avec des capacités de chargement de données (TanStack Router, Remix)

Des bibliothèques comme TanStack Router et Remix offrent des mécanismes de chargement de données intégrés qui s'intègrent de manière transparente au routage. Ces bibliothèques fournissent souvent des fonctionnalités comme :

L'utilisation d'une telle bibliothèque peut simplifier considérablement le chargement des données et améliorer les performances, en particulier pour les applications complexes.

Rendu Côté Serveur (SSR) et Génération de Site Statique (SSG)

Pour un meilleur SEO et une meilleure performance au chargement initial, envisagez d'utiliser le SSR ou le SSG avec des frameworks comme Next.js ou Gatsby. Ces frameworks vous permettent de récupérer les données sur le serveur ou au moment de la compilation et de servir du HTML pré-rendu au client. Cela élimine le besoin pour le client de récupérer des données lors du chargement initial, ce qui se traduit par une expérience plus rapide et plus favorable au SEO.

7. Travailler avec Différents Types de Routeurs

React Router v6 fournit différentes implémentations de routeur pour s'adapter à divers environnements et cas d'utilisation :

Choisissez le type de routeur qui convient le mieux aux exigences et à l'environnement de votre application.

Conclusion

React Router v6 offre une solution de routage complète et flexible pour les applications React. En comprenant et en appliquant les modèles de navigation discutés dans cet article de blog, vous pouvez construire des applications web robustes, conviviales et maintenables. Du routage déclaratif avec <Routes> et <Route> aux routes dynamiques avec paramètres d'URL, en passant par la navigation programmatique avec useNavigate et des stratégies de chargement de données efficaces, React Router v6 vous donne le pouvoir de créer des expériences de navigation fluides pour vos utilisateurs. Envisagez d'explorer des bibliothèques de routage avancées et des frameworks SSR/SSG pour un contrôle et une optimisation des performances encore plus grands. N'oubliez pas d'adapter ces modèles aux exigences spécifiques de votre application et de toujours privilégier une expérience utilisateur claire et intuitive.