Aller au contenu

React Router

Permettre de passer d’une page à l’autre dans votre application React.

Manuel

React Router

Pour l'installer dans votre projet :

console
npm i react-router-dom
npm i @types/react-router-dom --save-dev

Exemple de SPA avec Router

App.tsx
import {
  BrowserRouter,
  Routes,
  Route,
  Outlet,
  useParams,
} from 'react-router-dom';

import './App.css';

function Modele() {
  return (
    <div>
      <a href="/">Page principale</a>&nbsp;
      <a href="/dadams">Douglas Adams</a>&nbsp;
      <a href="/oscard">Orson Scott Card</a>
      <br />
      <Outlet />
    </div>
  );
}
function PagePrincipale() {
  return <h1>Page principale</h1>;
}

function DouglasAdams() {
  return (
    <>
      <h1>Page de Douglas Adams</h1>&nbsp;
      <a href="/livre/1">Livre 1</a>&nbsp;
      <a href="/livre/2">Livre 2</a>&nbsp;
    </>
  );
}

function OrsonScottCard() {
  return <h1>Page de Orson Scott Card</h1>;
}

function Livre() {
  const { id } = useParams();
  return <h1>Livre #{id}</h1>;
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Modele />}>
          <Route index element={<PagePrincipale />} />
          <Route path="dadams" element={<DouglasAdams />} />
          <Route path="oscard" element={<OrsonScottCard />} />
          <Route path="livre/:id" element={<Livre />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default App;

Différents éléments du projet monrouteur

BrowserRouter

Un <BrowserRouter> stocke l'emplacement actuel dans la barre d'adresse du navigateur en utilisant des URL propres et navigue en utilisant la pile d'historique intégrée du navigateur.

App.tsx
function App() {
  return (
    <BrowserRouter>
      // Le reste de l'application React
    </BrowserRouter>
  );
}

Manuel

BrowserRouter

Routes

L'élément <Routes> (au pluriel) indique l'ensemble des routes qui seront disponibles dans l'application. Doit contenir au moins un élément <Route> (au singulier).

app.tsx
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Modele />}/>
      </Routes>
    </BrowserRouter>
  );
}

Route

L'élément <Route> (au singulier) définit une page de l'application à afficher selon son URL.

Par exemple :

app.tsx
     <Route path="/dadams" element={<DouglasAdams />} />

Cette route indique que http://serveur/dadams pointe sur la composante DouglasAdams.

Routes imbriquées

L'élément <Route> (au singulier) peut contenir des routes enfants. Comme ceci :

app.tsx
     <Route path="/" element={<Modele />}>
          <Route index element={<PagePrincipale />} />
          <Route path="dadams" element={<DouglasAdams />} />
          <Route path="oscard" element={<OrsonScottCard />} />
          <Route path="livre/:id" element={<Livre />} />
        </Route>

Plusieurs choses importantes ici :

  • La route "/" est la route parent des autres. Lorsqu'un élément est mentionné dans la route parent, l'élément est généré avant celui de la route enfant. Il faut par contre indiquer dans l'élément parent à quel endroit faut-il générer l'élément enfant (avec l'élément <Outlet>) :

    app.tsx
        function Modele() {
        return (
            <div>
            <a href="/">Page principale</a>&nbsp;
            <a href="/dadams">Douglas Adams</a>&nbsp;
            <a href="/oscard">Orson Scott Card</a>
            <br />
            <Outlet />
            </div>
        );
        }
    
  • Le mot clé index indique l'élément qui sera généré lorsque l'utilisateur navigue à l'URL du parent.

Routes dynamiques

On peut placer un paramètre dans une route qui peut être lu par l'élément généré.

Dans la route, on peut avoir le paramètre :id :

app.tsx
<Route path="livre/:id" element={<Livre />} />

Dans l'élément, on accède au paramètre avec la fonction useParams() :

app.tsx
    function Livre() {
        const { id } = useParams();
        return <h1>Livre #{id}</h1>;
    }

HashRouter

Un <HashRouter> est une alternative à BrowserRouter qui stocke l'emplacement actuel dans la partie fragment (#) de l'URL plutôt que dans le chemin.

App.tsx
import { HashRouter, Routes, Route } from "react-router-dom";

function App() {
  return (
    <HashRouter>
      <Routes>
        <Route path="/" element={<Modele />}>
          <Route index element={<PagePrincipale />} />
          <Route path="dadams" element={<DouglasAdams />} />
        </Route>
      </Routes>
    </HashRouter>
  );
}

Les URLs générées ressemblent à ceci :

Page BrowserRouter HashRouter
Accueil monsite.com/ monsite.com/#/
Douglas Adams monsite.com/dadams monsite.com/#/dadams
Livre #3 monsite.com/livre/3 monsite.com/#/livre/3

Manuel

HashRouter

BrowserRouter vs HashRouter

La différence fondamentale est ce que le serveur web reçoit lors d'une requête :

  • Avec BrowserRouter, le serveur reçoit le chemin complet (ex. : /dadams). Si le serveur ne connaît pas cette route, il retourne une erreur 404.
  • Avec HashRouter, le serveur ne reçoit jamais la partie après le #. Il reçoit toujours / et le navigateur gère le reste localement. Aucune configuration serveur n'est nécessaire.

Impact sur le déploiement d'une SPA

C'est là que la différence devient concrète.

Problème avec BrowserRouter : Quand un utilisateur visite directement monsite.com/dadams ou rafraîchit la page, le serveur cherche un fichier à l'emplacement /dadams. Comme ce fichier n't'existe pas (c'est React qui gère la navigation), le serveur retourne une erreur 404.

Solution avec BrowserRouter : Il faut configurer le serveur pour rediriger toutes les requêtes vers index.html afin que React Router prenne le relais. Sur Azure Static Web Apps, cela se fait avec le fichier staticwebapp.config.json :

staticwebapp.config.json
{
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/dist/*.{svg,png,jpg,gif}", "/dist/assets/*"]
  }
}

Avantage de HashRouter : Aucune configuration serveur requise. Ça fonctionne sur n'importe quel hébergement de fichiers statiques (GitHub Pages, un simple serveur Apache, etc.) sans modification.

Quand utiliser lequel ?

Critère BrowserRouter HashRouter
URLs propres (sans #) Oui Non
Configuration serveur requise Oui Non
Référencement (SEO) Meilleur Plus faible
Hébergement simple (GitHub Pages, S3) Nécessite config Fonctionne d'emblée
Applications internes / prototypage Oui Oui

En production avec un hébergement que vous contrôlez (Azure, Vercel, Netlify), privilégiez BrowserRouter pour les URLs propres. Pour un hébergement statique sans configuration possible, HashRouter est la solution simple.