Aller au contenu principal
Dev Serein
Retour aux solutions
FrontendIntermédiaire

React et Next.js : corriger Hydration failed

Trouver la différence entre le HTML serveur et le premier rendu React, puis corriger les dates, données et accès au navigateur.

Le HTML serveur et le premier rendu React doivent être identiques. Dans Next.js, "use client" n’empêche pas le pré-rendu serveur.

Localiser la première différence

Reproduisez l’erreur avec le serveur de développement et ouvrez la console. Lisez la première erreur et la pile de composants, puis isolez la partie qui diffère. Si le problème n’apparaît qu’en production, reproduisez avec le build de production du projet.

Cause possible Exemple Correction à examiner
Valeur différente à chaque rendu Date.now(), Math.random() Fournir une valeur initiale stable depuis le serveur
Donnée propre au navigateur localStorage, taille de fenêtre Lire après le montage, avec un rendu initial identique
Date formatée différemment Locale ou fuseau implicite Fixer les paramètres ou formater après le montage
HTML invalide Un div dans un p, des boutons imbriqués Corriger la structure que le navigateur répare
Données serveur et client différentes Deux chargements indépendants Réutiliser le même instantané initial
HTML modifié avant React Extension, CDN ou bibliothèque CSS Tester sans extension et vérifier la configuration

Faites un essai avec un profil de navigateur sans extension. Cela aide à distinguer une modification externe d’un bug de l’application.

Lire localStorage après le montage

Un test typeof window !== "undefined" placé dans le rendu peut produire deux contenus différents. Utilisez plutôt une valeur initiale commune, puis lisez le navigateur dans un effet :

"use client";

import { useEffect, useState } from "react";

export default function PreferenceAffichage() {
  const [preference, setPreference] = useState("automatique");

  useEffect(() => {
    try {
      const valeur = window.localStorage.getItem("affichage");
      if (valeur === "clair" || valeur === "sombre") {
        setPreference(valeur);
      }
    } catch {
      // Le stockage peut être bloqué ; la valeur par défaut reste utilisable.
    }
  }, []);

  return <p>Affichage : {preference}</p>;
}

Le serveur et le premier rendu client affichent « automatique ». L’effet applique ensuite la préférence. Ce décalage est adapté à une préférence secondaire ; pour un thème global sans flash, utilisez l’intégration de thème prévue par votre framework plutôt que de masquer toute la page.

Stabiliser les dates et les identifiants

Transmettez une date ISO déjà fixée dans les données initiales. Pour une sortie strictement stable, vous pouvez d’abord afficher cette même chaîne :

export function DatePublication({ iso }: { iso: string }) {
  return <time dateTime={iso}>{iso}</time>;
}

Formatez-la ensuite selon les besoins : sur le serveur avec une chaîne transmise telle quelle, ou après montage pour respecter le fuseau du visiteur. Ne générez pas une nouvelle date indépendamment à chaque rendu.

Pour relier les champs et leurs labels, useId fournit des identifiants compatibles avec le rendu serveur lorsque l’arbre de composants correspond. Pour les clés de liste, utilisez l’identifiant stable des données ; useId n’est pas destiné à remplacer ces clés.

Isoler une bibliothèque qui exige le navigateur

Dans Next.js, si un widget ne peut réellement pas fonctionner au serveur, un Client Component peut le charger sans SSR :

"use client";

import dynamic from "next/dynamic";

const Carte = dynamic(() => import("./Carte"), {
  ssr: false,
  loading: () => <p>Chargement de la carte…</p>,
});

export default function CarteClient() {
  return <Carte />;
}

Le fichier Carte doit exister et exporter le composant par défaut. Avec l’App Router, ssr: false doit être placé dans un Client Component. Réservez cette approche au widget concerné : son contenu n’est plus fourni dans le HTML serveur.

Vérifier la correction

Rechargez directement la page, puis testez la navigation interne, une session sans stockage et les préférences déjà enregistrées. Vérifiez l’absence d’erreur et le bon fonctionnement des interactions, pas seulement l’apparence.

suppressHydrationWarning est une exception locale pour une différence inévitable, limitée à un niveau. Ce n’est pas une réparation du rendu. Retirer le SSR de toute la page ou repousser tout son contenu au montage peut cacher la cause et dégrader le chargement.

Ressources

SUPER CALCULATEUR / CONNEXION ÉTABLIE

UN PASSAGE SECRET DANS DEV SEREIN

Bienvenue sur
Code Lyoko.

Le monde virtuel n’était qu’à quelques lettres.
Jérémie a ouvert la connexion. À toi de jouer.

Des arbres infinis, des chemins suspendus. Garde un œil sur la mer numérique.

LYOKO-GUERRIERS

Aelita · Yumi · Ulrich · Odd

SCAN DU TERRITOIREFORÊT / 01

ALERTE XANA · TOUR ACTIVÉE

On compte sur toi, Aelita.