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.
📋 Table of Contents
- Was Flüssigkeitszufuhr ist
- Ursache 1: Verwendung reiner Browser-APIs während des Renderns
- Ursache 2: Datum und Uhrzeit
- Ursache 3: Zufällige Werte
- Ursache 4: Ungültige HTML-Verschachtelung
- Ursache 5: Browsererweiterungen, die HTML ändern
- Ursache 6: Bedingtes Rendering basierend auf dem Clientstatus
- Das Nur-Client-Komponentenmuster
- Häufig gestellte Fragen
- Fazit
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.
🔗 Share this article
✍️ Leave a Comment