🌐 Detecting your location…

So beheben Sie den Fehler „Hydration Failed“ in Next.js: Komplettlösung

⏱️5 min read  ·  1,058 words

Der FehlerDie Hydratation ist fehlgeschlagen, weil die ursprüngliche Benutzeroberfläche nicht mit dem übereinstimmt, was auf dem Servergerendert wurde (oder „Textinhalt stimmt nicht mit dem vom Server gerenderten HTML überein“) in Next.js bedeutet, dass sich der vom Server gerenderte HTML-Code von dem unterscheidet, der von React auf dem Client gerendert wird. Hier erfahren Sie, warum es passiert und wie Sie jede Ursache beheben können.

Was Flüssigkeitszufuhr ist

Next.js rendert Ihre Seite auf dem Server (SSR) in HTML, sendet sie zur schnellen Erstanzeige an den Browser und „hydratisiert“ sie dann durch React – wodurch Interaktivität entsteht. Hydration erfordert, dass der vom Server gerenderte HTML-Code und der erste Render des Clients genau übereinstimmen. Wenn sie unterschiedlich sind, gibt React einen Hydratationsfehler aus, da die Nichtübereinstimmung nicht ausgeglichen werden kann.

Ursache 1: Verwendung reiner Browser-APIs während des Renderns

// 🐛 window/localStorage don't exist on the server → mismatch
function Component() {
  const theme = localStorage.getItem('theme');   // ❌ undefined on server
  return <div className={theme}>...</div>;
}

// ✅ Access browser APIs only after mount (in useEffect)
function Component() {
  const [theme, setTheme] = useState(null);

  useEffect(() => {
    setTheme(localStorage.getItem('theme'));   // runs only on client
  }, []);

  return <div className={theme || 'default'}>...</div>;
}

Ursache 2: Datum und Uhrzeit

// 🐛 The server and client render at different times → mismatch
function Component() {
  return <div>{new Date().toLocaleString()}</div>;   // ❌ differs
}

// ✅ Render the date only on the client
function Component() {
  const [date, setDate] = useState(null);
  useEffect(() => { setDate(new Date().toLocaleString()); }, []);
  return <div>{date ?? 'Loading...'}</div>;
}

Ursache 3: Zufällige Werte

// 🐛 Math.random() produces different values on server vs client
function Component() {
  const id = Math.random();   // ❌ different each render
  return <div id={id}>...</div>;
}

// ✅ Use React's useId for stable IDs, or generate in useEffect
import { useId } from 'react';
function Component() {
  const id = useId();   // stable across server and client
  return <div id={id}>...</div>;
}

Ursache 4: Ungültige HTML-Verschachtelung

// 🐛 Invalid nesting gets "corrected" by the browser, causing mismatch
<p>
  <div>Content</div>   {/* ❌ div inside p is invalid */}
</p>
// The browser moves the div out, but React's tree still has it nested

// ✅ Use valid HTML nesting
<div>
  <div>Content</div>   {/* valid */}
</div>
// Common culprits: div/p inside p, block elements inside inline elements,
// invalid table structure

Ursache 5: Browsererweiterungen, die HTML ändern

// Some browser extensions inject attributes/elements into your HTML
// before React hydrates, causing a mismatch (e.g., Grammarly, dark mode extensions)

// This often shows as a mismatch on the body or specific elements.
// You can suppress the warning on a specific element if needed:
<body suppressHydrationWarning>
  {/* Use sparingly - only when the mismatch is expected/harmless */}
</body>
// But first verify it's an extension, not a real bug in your code.

Ursache 6: Bedingtes Rendering basierend auf dem Clientstatus

// 🐛 Rendering differently based on something only known on the client
function Component() {
  const isMobile = window.innerWidth < 768;   // ❌ window undefined on server
  return isMobile ? <Mobile /> : <Desktop />;
}

// ✅ Start with a consistent server render, adjust after mount
function Component() {
  const [isMobile, setIsMobile] = useState(false);   // consistent default

  useEffect(() => {
    setIsMobile(window.innerWidth < 768);
    const onResize = () => setIsMobile(window.innerWidth < 768);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  return isMobile ? <Mobile /> : <Desktop />;
}

Das Nur-Client-Komponentenmuster

// For components that genuinely can't be server-rendered,
// use dynamic import with ssr: false
import dynamic from 'next/dynamic';

const ClientOnlyChart = dynamic(() => import('./Chart'), {
  ssr: false,   // skip server rendering entirely
  loading: () => <div>Loading chart...</div>,
});
// The component renders only on the client - no hydration mismatch possible

Häufig gestellte Fragen

F: Was verursacht am häufigsten Fehler bei der Flüssigkeitszufuhr?
A: Verwendung reiner Browser-APIs (Window, LocalStorage) während des Renderns, Rendern von Datums-/Uhrzeitwerten oder Zufallswerten, die zwischen Server und Client unterschiedlich sind, und ungültige HTML-Verschachtelung. Der rote Faden: Auf dem Server wird etwas anders gerendert als auf dem Client. Verschieben Sie kundenspezifische Logik in useEffect.

F: Wie verwende ich localStorage ohne Hydratationsfehler?
A: Greifen Sie während des Renderns nicht darauf zu (es ist auf dem Server nicht definiert). Lesen Sie es in useEffect (das nur auf dem Client läuft) und speichern Sie den Wert in state. Rendern Sie zunächst einen konsistenten Standard und aktualisieren Sie ihn dann nach dem Mounten. Dadurch bleiben Server- und Client-Renderings übereinstimmend.

F: Mein Trinkfehler wird durch eine Browsererweiterung verursacht. Was mache ich?
A: Erweiterungen wie Grammarly injizieren Attribute vor der Hydratation. Stellen Sie sicher, dass es sich um die Erweiterung handelt (Testen Sie im Inkognitomodus mit deaktivierten Erweiterungen). Wenn es harmlos ist, können SiesuppressHydrationWarninghinzufügen auf das betroffene Element – verwenden Sie es jedoch sparsam und nur für nachweislich harmlose externe Modifikationen, nicht um echte Fehler zu verbergen.

F: Wann sollte ich den dynamischen Import mit ssr: false verwenden?
A: Für Komponenten, die wirklich nicht vom Server gerendert werden können oder sollten – solche, die stark auf Browser-APIs oder reine Client-Bibliotheken von Drittanbietern angewiesen sind oder die nicht von SSR profitieren. Es überspringt das Server-Rendering vollständig und eliminiert Hydratations-Diskrepanzen für diese Komponente, allerdings ohne SSR-Vorteile.

F: Warum funktioniert es in der Entwicklung, aber manchmal tritt der Fehler auf?
A: Fehlanpassungen der Flüssigkeitszufuhr können zeitweise auftreten, wenn sie vom Zeitpunkt (Daten), Zufälligkeit oder externen Faktoren (Verlängerungen) abhängen. Sie sind echte Käfer, auch wenn sie nur gelegentlich auftreten. Reproduzieren Sie zuverlässig, indem Sie die Unterschiede zwischen Server- und Client-Rendering identifizieren – normalerweise Browser-APIs, Zeit oder Zufallswerte.

Fazit

Next.js-Hydratierungsfehler bedeuten, dass der vom Server gerenderte HTML-Code nicht mit dem ersten Rendering des Clients übereinstimmt. Die Ursachen sind konsistent:Nur-Browser-APIs (Fenster, LocalStorage), die beim Rendern verwendet werden, abweichende Datums-/Zeitangaben oder Zufallswerte, ungültige HTML-Verschachtelung und clientspezifisches bedingtes Rendering. Das Korrekturmuster ist dasselbe: Verschieben Sie die clientspezifische Logik nachuseEffect (das nur auf dem Client läuft), zunächst einen konsistenten Standard rendern und nach dem Mounten aktualisieren. Verwenden SieuseId für stabile IDs, gültige HTML-Verschachtelung unddynamic(..., ssr: false) für echte Client-only-Komponenten. Sobald Ihre Server- und Client-Renderings übereinstimmendes HTML erzeugen, ist die Hydratation erfolgreich. Das wichtigste mentale Modell: Alle Renderings müssen beim ersten Rendering auf Server und Client identisch sein – alles Client-spezifische gehört in useEffect.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা