14 nov. 2025·3 min de lecture

Checklist Next.js pour les mismatches d'hydratation des UIs générées par l'IA

Utilisez cette checklist Next.js pour repérer rapidement les divergences serveur/client : dates, aléatoire, accès à window et rendus instables.

Checklist Next.js pour les mismatches d'hydratation des UIs générées par l'IA

Ce qu'est réellement un mismatch d'hydratation (en clair)

Avec le rendu serveur, Next.js envoie d'abord du HTML pour que la page s'affiche rapidement. Ensuite React s'exécute dans le navigateur et « hydrate » ce HTML en attachant les gestionnaires d'événements et en rendant à nouveau la même UI avec les mêmes entrées.

Un mismatch d'hydratation survient lorsque le HTML côté serveur ne correspond pas à ce que React produit lors du premier rendu côté client. React émet un avertissement parce qu'il ne peut pas supposer en toute sécurité que le DOM est cohérent.

Concrètement, cela peut se traduire par un avertissement dans la console, un léger clignotement quand React remplace des parties de la page, des boutons qui ne répondent pas un instant, ou du texte qui change juste après le chargement. Parfois c'est subtil. Parfois ça casse des formulaires, l'UI d'authentification, et tout ce qui dépend d'un DOM stable.

Le code UI généré par l'IA provoque plus souvent ce problème parce qu'il a tendance à mélanger des valeurs propres au navigateur dans le rendu sans garde-fous. Exemples typiques : lire window pendant le rendu, formater des dates différemment côté serveur et client, ou utiliser de l'aléatoire pour choisir une couleur, un ID ou une valeur par défaut.

Règle simple : si le serveur et le navigateur peuvent produire des réponses différentes, n'utilisez pas directement cette valeur pendant le rendu.

Ce que vous pouvez généralement ignorer vs ce qu'il faut corriger :

  • Risque faible : une petite différence de className qui n'affecte ni la mise en page ni les entrées utilisateur.
  • Corriger rapidement : tout ce qui provoque un saut de contenu, la réinitialisation d'inputs, un changement d'état d'auth, ou la disparition d'éléments.
  • Toujours corriger : tout ce qui touche à l'identité ou à la sécurité (par exemple afficher le mauvais état utilisateur).

Tri rapide : reproduire et isoler le mismatch

Un avertissement d'hydratation est spécifique : le serveur a envoyé du HTML, puis le navigateur a essayé d'y attacher React, et le premier rendu client ne correspondait pas à ce qui était déjà présent. Avant de vous lancer, assurez-vous que vous ne voyez pas en réalité un échec de fetch (données vides), une redirection, ou un décalage de mise en page qui ressemble à un problème d'hydratation.

Reproduisez en build de production. Le mode dev peut ajouter des rendus et des avertissements supplémentaires qui brouillent la piste.

Un flux de triage rapide :

  • Lancez un build de production, démarrez l'app localement et rafraîchissez la page qui affiche l'avertissement.
  • Testez à la fois un rechargement complet (hard refresh) et une navigation côté client vers la même route.
    • Si ça casse seulement au rechargement : suspectez une différence dans l'output SSR.
    • Si ça casse seulement après navigation : suspectez l'état client ou des effets.
  • Lisez l'indice exact dans l'avertissement React (souvent un élément, un nœud texte ou un attribut spécifique).
  • Supprimez temporairement des morceaux de la page jusqu'à ce que l'avertissement disparaisse, puis réintégrez-les jusqu'à trouver le plus petit composant qui échoue encore.
  • Une fois que vous avez le plus petit composant défaillant, comparez ce qu'il rend côté serveur et côté client. Une seule différence de caractère suffit.

Pendant que c'est frais, notez :

  • La route et les étapes exactes (rechargement vs navigation)
  • L'élément ou le texte nommé par React
  • Si le mismatch concerne le contenu (texte), des attributs (class, style) ou la structure (wrapper supplémentaire)
  • Si les données sont présentes au premier affichage ou apparaissent plus tard

Un pattern courant dans les widgets IA : un titre « Welcome, Sam » rendu côté serveur comme « Welcome » (pas d'utilisateur encore), puis le client complète instantanément le nom depuis le localStorage. C'est un mismatch, et le test « refresh vs navigation » le rend souvent évident.

Vérifications rapides en 10 minutes

Les gains les plus rapides viennent de l'identification de toute valeur qui peut rendre différemment côté serveur et dans le navigateur. Vous ne réparez pas tout encore. Vous identifiez l'entrée unique qui change entre le HTML serveur et le premier rendu client.

Un scan rapide qui attrape la plupart des bugs générés par l'IA

Ouvrez le composant nommé dans l'avertissement (ou la page concernée) et cherchez les suspects habituels :

Date, Math.random, window, document, navigator, localStorage, sessionStorage.

Une routine simple :

  • Réduisez la page au plus petit composant qui déclenche encore l'avertissement.
  • Cherchez les valeurs dynamiques utilisées dans le JSX (texte, attributs, props) (heure, nombres aléatoires, vérifications de viewport).
  • Vérifiez les rendus conditionnels basés sur le viewport, l'user agent ou des media queries en JavaScript (pas en CSS).
  • Cherchez des key instables, des IDs générés, ou des noms de classes qui changent entre les exécutions.
  • Hardcodez la valeur suspecte (par exemple une date fixe) pour confirmer que l'avertissement disparaît.

Choisir la correction la plus sûre

La plupart des corrections suivent quelques patterns :

  • Rendre le rendu déterministe : calculez la valeur côté serveur et passez-la en prop.
  • Différer la valeur jusqu'après le montage : affichez un placeholder, puis mettez l'état dans useEffect.
  • Protéger les API propres au navigateur : vérifiez typeof window !== \"undefined\" avant de les lire.
  • Déplacer un widget en client-only quand il dépend véritablement de l'état du navigateur.

Checklist : dates, fuseaux horaires et formatage local

Debug the root cause
We isolate the smallest failing component and patch it the right way.

Les dates sont une cause fréquente de mismatches parce que le serveur et le navigateur peuvent ne pas être d'accord sur le « maintenant », le fuseau horaire ou les réglages locaux par défaut. Si le texte rendu diffère même légèrement, React se plaint.

Vérifications rapides

Cherchez l'UI qui transforme « now » en texte pendant le rendu :

  • new Date() ou Date.now() à l'intérieur du rendu du composant
  • Intl.DateTimeFormat(...) sans timeZone et locale explicites
  • Temps relatifs comme « à l'instant » calculés pendant le SSR
  • Timers ou comptes à rebours dépendant de la seconde courante
  • Côté serveur en UTC pendant que le navigateur utilise un fuseau local

Un pattern courant :

"Last updated: {new Date().toLocaleString()}"

Cela diffèrera presque toujours entre serveur et client.

Modèles de correction qui gardent les pages stables

Choisissez l'approche qui correspond aux besoins réels des utilisateurs :

  • Passez le timestamp comme donnée et affichez cette valeur exacte.
  • Formatez avec un fuseau horaire explicite (souvent UTC) et la locale choisie.
  • Si vous avez besoin d'un temps relatif, affichez un placeholder stable côté serveur, puis calculez après le montage.
  • Pour des horloges ou comptes à rebours en direct, rendez une valeur initiale fournie par le serveur puis démarrez la mise à jour dans un effet.

Questions Fréquentes

Qu'est-ce qu'un mismatch d'hydratation dans Next.js, en termes simples ?

Un mismatch d'hydratation se produit lorsque le HTML envoyé par Next.js depuis le serveur ne correspond pas à ce que React rend côté client lors du tout premier rendu. React émet alors un avertissement parce qu'il ne peut pas attacher en toute sécurité des gestionnaires d'événements à un DOM qu'il n'a pas créé.

Vous remarquerez souvent un avertissement dans la console, un bref clignotement, ou une UI qui change juste après le chargement.

Comment savoir si le problème est lié au SSR ou à l'état client ?

Commencez par reproduire le problème en build de production, pas en mode dev. Ensuite, comparez un rechargement complet (hard refresh) avec une navigation client-side vers la même route.

S'il casse uniquement au rechargement, c'est généralement une différence SSR vs premier rendu client. S'il casse surtout après une navigation, il s'agit souvent de l'état client, des effets ou des données mises en cache.

Quelles sont les choses les plus rapides à chercher quand je vois un avertissement d'hydratation ?

Cherchez tout ce qui peut produire un rendu différent sur le serveur et dans le navigateur pendant le rendu : new Date(), Date.now(), Math.random(), formats locaux, window, document, navigator, localStorage et sessionStorage.

Si l'une de ces valeurs influence du texte, des attributs ou quels éléments sont rendus, vous avez un candidat sérieux au mismatch.

Pourquoi les dates et les fuseaux horaires causent-ils tant de mismatches d'hydratation ?

Parce que le serveur et le navigateur peuvent diverger sur le « maintenant », le fuseau horaire ou la locale par défaut. Même une différence d'un caractère dans un timestamp formaté suffit pour déclencher un avertissement.

La solution la plus sûre est de rendre un timestamp stable fourni par les données (ou une valeur connue côté serveur) et de ne calculer le « temps relatif » qu'après le montage du composant.

Pourquoi l'utilisation de Math.random() dans le JSX casse-t-elle l'hydratation ?

Parce que Math.random() s'exécute deux fois : une fois sur le serveur, puis à nouveau dans le navigateur. Si vous appelez Math.random() pendant le rendu pour choisir un ID, une couleur, une variante ou une key, le serveur et le client choisiront probablement des résultats différents.

Rendez le premier rendu déterministe en utilisant des IDs stables issus des données, ou déplacez l'aléatoire après le montage.

Quelle est la bonne manière d'utiliser window ou localStorage sans provoquer de mismatch ?

Lire les API propres au navigateur pendant le rendu fait que le client produit un rendu différent du serveur, car le serveur ne peut pas lire ces valeurs. Un exemple courant est d'afficher une UI « connectée » basée sur un token lu dans localStorage.

Une solution pratique consiste à rendre une coque (shell) neutre et stable côté serveur, puis à peupler l'état dérivé du navigateur dans useEffect après l'hydratation.

Comment éviter les mismatches liés à l'état d'auth (connecté vs déconnecté) ?

Si le serveur rend « déconnecté » mais que le client rend immédiatement « connecté » après avoir lu un token, React voit deux marquages différents. Cela peut aussi réinitialiser des champs de formulaire ou rendre des boutons temporairement inopérants.

L'approche propre consiste à faire en sorte que le serveur et le premier rendu client concordent en transmettant l'état de session initial depuis le serveur quand c'est possible, ou en affichant un état de chargement/squelette cohérent jusqu'à confirmation de l'authentification.

La logique responsive peut-elle provoquer des mismatches d'hydratation ?

Oui. Si vous utilisez window.innerWidth ou matchMedia() pendant le rendu pour choisir entre deux arbres de composants différents, le serveur devine la taille d'écran de l'utilisateur.

Préférez rendre le même DOM des deux côtés et laisser le CSS gérer la présentation. Si vous devez changer le markup, faites-le après le montage afin que le premier rendu reste stable.

Quand suppressHydrationWarning est-il acceptable, et quand est-ce risqué ?

À n'utiliser que pour de petits textes non interactifs où une différence ponctuelle est acceptable. C'est en fait dire à React « ne m'avertis pas ici », pas rendre l'UI réellement cohérente.

Évitez de l'utiliser sur des champs de formulaire, de l'UI conditionnée par l'auth, ou tout élément affectant l'identité, les permissions ou les actions utilisateur.

Que faire si je ne trouve pas le mismatch dans une base de code Next.js générée par IA ?

Si vous avez éliminé les causes évidentes et que l'avertissement continue de se déplacer, la base de code a souvent plusieurs sources de divergence serveur/client. C'est fréquent dans des prototypes générés par IA où des lectures dépendantes du navigateur, des clés aléatoires et des formats de date se retrouvent mélangés dans les chemins de rendu.

FixMyMess peut effectuer un audit rapide pour localiser le composant exact et la valeur qui causent le mismatch, puis réparer sans désactiver SSR pour tout le projet.