What is hydration and what causes hydration mismatch errors?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Hydration attaches listeners and state to server-rendered HTML, making it interactive. A mismatch happens when the client's first render produces different markup than the server sent — usually from non-deterministic values like Date.now(), Math.random(), localStorage reads, or timezone formatting.
Detailed explanation
Next.js sends fully-formed HTML for fast first paint, then React hydrates: walks the DOM, reconstructs component trees, binds events without recreating elements. If the first client render disagrees with that HTML, React warns and repairs on the client, sacrificing performance. Common culprits: timestamps formatted differently per locale/timezone, random IDs generated independently, reading localStorage or theme during render, browser-only checks like typeof window inline, invalid nesting browsers auto-correct (<p><div>), or browser extensions mutating the DOM. Fixes: compute such values inside useEffect (after hydration), use suppressHydrationWarning for single-node known divergence like the theme class on html, or gate browser-dependent UI behind a mounted flag. The principle: the first client render must match the server exactly.
Example
// ❌ mismatch: server & client may format times differently
function Clock() {
return <span>{new Date().toLocaleTimeString()}</span>;
}
// ✅ stable first render, update after mount
function SafeClock() {
const [now, setNow] = useState(null);
useEffect(() => setNow(new Date().toLocaleTimeString()), []);
return <span suppressHydrationWarning>{now ?? '--:--:--'}</span>;
}Interview tip
Define hydration as 'attaching behavior to existing HTML', list your top three mismatch causes from experience, and show the mounted-state fix.
Common mistakes
- Calling hydration 're-rendering everything'.
- Not recognizing localStorage reads during render as a cause.