Hydration Mismatch
Hydration Mismatch
A Hydration Mismatch occurs when the HTML generated by the Server (during SSR or SSG) does not exactly match the HTML that React attempts to render on the Client during the hydration phase.
React expects the client-side Virtual DOM to perfectly mirror the server-provided DOM. If they differ, React throws a Hydration Mismatch Error.
Why Mismatches are Dangerous
When React detects a mismatch, it cannot safely attach event listeners. It assumes the server HTML is corrupted or out-of-sync.
As a fallback, React throws away the entire server-rendered HTML tree and aggressively re-renders the component from scratch.
This ruins the performance benefits of SSR, causes jarring visual flickering for the user, and wastes CPU cycles.
Common Causes of Mismatches
-
Using Browser-Only APIs:
If you checkwindow.innerWidthto conditionally render a mobile sidebar, this will fail. The server doesn’t have awindow, so it renders the desktop version. The client does have a window, so it tries to render the mobile version. Mismatch!// ❌ Causes Mismatch function Sidebar() { const isMobile = typeof window !== 'undefined' && window.innerWidth < 768; return isMobile ? <MobileNav /> : <DesktopNav />; } -
Using Non-Deterministic Data:
If you useMath.random()orDate.now()directly in your render logic, the server will generate one random number, and the client will generate a completely different one during hydration.// ❌ Causes Mismatch function UUIDGenerator() { return <div>Your ID is: {Math.random()}</div>; } -
Invalid HTML Nesting:
Browsers automatically correct malformed HTML. If your React component renders a<p>inside another<p>, the server sends exactly that. But the browser intercepts it and breaks it into sibling<p>tags. When React tries to hydrate, its Virtual DOM (nested) no longer matches the physical DOM (siblings).
How to Fix Mismatches
The standard way to fix browser-dependent mismatches is to use a useEffect hook (which only runs on the client, never on the server) to wait until hydration is complete before rendering dynamic content.
// ✅ The fix for browser APIs
function Sidebar() {
const [isMounted, setIsMounted] = useState(false);
// This only runs on the client AFTER hydration!
useEffect(() => {
setIsMounted(true);
}, []);
// Server renders this, Client hydrates this
if (!isMounted) return <DesktopNav />;
// Client quickly updates to this if necessary
const isMobile = window.innerWidth < 768;
return isMobile ? <MobileNav /> : <DesktopNav />;
}
Interview Questions
Q: What is a Hydration Mismatch?
A: It occurs when the initial static HTML rendered by the server does not exactly match the DOM structure that React calculates when it boots up on the client. This mismatch forces React to destroy and re-create the DOM nodes on the client, completely defeating the performance benefits of SSR.