Leçon 11 / 15

Réserver les composants client aux interactions

35 min Next.js — performance, SEO et mise en production Gratuit

Objectif : Extraire une commande interactive dans un composant client minimal, sans transformer la page ni le détail de l’itinéraire en composants clients.

Une page peut avoir besoin d’une interaction sans que tout son contenu nécessite JavaScript dans le navigateur. Si vous placez la directive client trop haut, Next.js doit aussi préparer le code de composants qui pourraient rester rendus sur le serveur. Dans cette leçon, vous ajoutez une commande locale au suivi des performances : afficher ou masquer ses informations. La fiche d’itinéraire reste rendue côté serveur ; seul le contrôle qui possède un état devient un composant client.

Choisir une frontière client étroite

La directive use client marque le point d’entrée d’un sous-arbre qui doit s’exécuter dans le navigateur. Elle doit apparaître avant les imports du fichier concerné. Ce choix entraîne l’hydratation de ce sous-arbre : le navigateur associe les gestionnaires d’événements au HTML déjà rendu pour que les contrôles répondent aux actions de la personne. Vous avez déjà déplacé l’affichage statique du détail dans un composant serveur ; cette séparation reste inchangée. Pour ne pas ajouter de fichier hors du contrat du projet, le contrôle est placé dans components/suivi-performances.tsx, le composant déjà prévu pour les mesures. Il n’accède ni au DOM directement ni à des données non sérialisables.

Ajouter l’état local au composant de suivi

Remplacez le contenu de components/suivi-performances.tsx par ce composant complet. L’état initial masqué évite d’ajouter au contenu principal une information de suivi qui n’est pas consultée. Le bouton modifie uniquement cet état local ; l’attribut aria-expanded communique son ouverture aux technologies d’assistance.

Texte
"use client";

import { useState } from "react";

export default function SuiviPerformances() {
  const [mesuresVisibles, setMesuresVisibles] = useState(false);

  return (
    <section className="rando-mesures" aria-label="Suivi des performances">
      <button
        type="button"
        aria-expanded={mesuresVisibles}
        onClick={() => setMesuresVisibles((visible) => !visible)}
      >
        {mesuresVisibles ? "Masquer les mesures" : "Afficher les mesures"}
      </button>
      {mesuresVisibles && (
        <p>Les mesures de performance seront consultables ici.</p>
      )}
    </section>
  );
}

Le résultat initial est un bouton « Afficher les mesures ». Au clic, son libellé devient « Masquer les mesures » et le paragraphe apparaît ; un second clic le retire. useState conserve cette valeur entre les rendus du composant. Elle ne doit pas être placée dans la page entière : un état qui ne concerne que ce contrôle n’a pas besoin d’élargir la frontière client.

Rendre le contrôle depuis le composant serveur

Le composant serveur qui compose la page peut importer et afficher ce composant client. Dans app/layout.tsx, conservez le layout existant et ajoutez le composant de suivi dans l’emplacement prévu par le squelette, après le pied de page. Ne mettez pas use client dans le layout, dans la page dynamique ni dans itineraire.tsx : ces fichiers restent des composants serveur.

Texte
// Extrait de composition dans app/layout.tsx
import SuiviPerformances from "@/components/suivi-performances";

// Dans le JSX du layout, à la place de l’élément de mesures vide :
<SuiviPerformances />

Cette composition transmet aucune propriété : le composant n’a besoin que de son propre état. Si vous lui transmettez plus tard une valeur issue d’un composant serveur, choisissez des données simples sérialisables et limitez-les au strict nécessaire. Le contenu détaillé de l’itinéraire et ses métadonnées continuent ainsi d’être produits par leurs fichiers serveur dédiés. L’extrait indique l’emplacement de l’import et du rendu à intégrer dans le layout existant ; conservez tous ses éléments et imports actuels. Le projet emploie une feuille de style unique et ne demande ici aucune modification de HTML de page, de CSS ou de configuration.

Vérifier la frontière et le résultat

Lancez le serveur de développement et ouvrez /randonnees/cretes-du-jura. Vérifiez que le détail, son image et ses informations restent affichés avant toute interaction, puis testez les deux états du bouton au clavier et à la souris. Contrôlez également qu’aucune erreur d’hydratation n’apparaît dans la console. Sur un build de production, comparez le JavaScript client transféré avec la référence établie précédemment. Cette interaction implique un petit sous-arbre client, mais le seul ajout de la directive ne prouve pas à lui seul que le budget est respecté : mesurez le résultat et consignez-le avec les mêmes conditions que votre référence. La règle de non-régression reste applicable.

À retenir

  • Placez `use client` dans le composant qui porte réellement l’interaction, pas dans la page entière.
  • Gardez l’état local au contrôle qui en a besoin ; le contenu statique de l’itinéraire reste rendu côté serveur.
  • Rendez le contrôle accessible avec un bouton natif et un état `aria-expanded` cohérent.
  • Vérifiez le comportement, l’hydratation et le JavaScript transféré sur un build de production avant de valider le changement.

Dans la prochaine leçon, vous chargerez à la demande une fonctionnalité secondaire afin de limiter davantage le code nécessaire au premier affichage.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.