Hydration and its errors: when server HTML and the client disagree
Hydration attaches React to server-rendered HTML. Learn what causes mismatches (dates, random values, window checks, browser extensions), the right fixes, when suppressHydrationWarning is allowed, and why hydration cost leads to islands.
Comes up in: React, Debugging
Learn#
Megha’s server-rendered page flashes and logs “Hydration failed” on some users’ machines. On those machines the header’s date shows yesterday, then jumps to today.
Hydration is how React takes over server HTML: it renders the same components in the browser, matches the result to the existing DOM, and attaches event handlers instead of recreating everything. That only works if the first client render produces exactly the same output:
import { GlobalRegistrator } from "@happy-dom/global-registrator";
GlobalRegistrator.register(); // a DOM for Node; in a browser you already have one
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
const { createElement: h, useEffect, useState, act } = await import("react");
const { renderToString } = await import("react-dom/server");
const { hydrateRoot } = await import("react-dom/client");
let isServer = true;
function BadClock() { // different output on server and client: a mismatch
return h("p", null, isServer ? "Rendered on the server" : "Rendered in the browser");
}
function GoodClock() { // same first render everywhere, then update after hydration
const [where, setWhere] = useState("Loading…");
useEffect(() => setWhere("Rendered in the browser"), []);
return h("p", null, where);
}
for (const Clock of [BadClock, GoodClock]) {
isServer = true;
const box = document.createElement("div");
box.innerHTML = renderToString(h(Clock)); // the HTML the server sent
isServer = false;
const problems = [];
await act(() => hydrateRoot(box, h(Clock), { onRecoverableError: (e) => problems.push(e.message.split(".")[0]) }));
console.log(Clock.name, "→", box.textContent, "|", problems.length ? problems[0] : "no hydration error");
}Output (verified)
BadClock → Rendered in the browser | Hydration failed because the server rendered text didn't match the client GoodClock → Rendered in the browser | no hydration error
A hydration mismatch comes from anything that differs between server and browser: dates and time zones, Math.random(), typeof window checks, localStorage, invalid HTML nesting, and browser extensions that edit the page.
Page
- <p>Rendered on the server</p>
State
empty
Console
empty
The server renders "Rendered on the server" and sends it as HTML. Users see it before any JavaScript runs.
Read the steps as text
- The server renders "Rendered on the server" and sends it as HTML. Users see it before any JavaScript runs.
- The bundle loads. hydrateRoot renders the same component in the browser and expects identical output.
- The text differs. React reports a hydration error and re-renders that part on the client, throwing away the server HTML there.
- The fix: render the same first output everywhere ("Loading…"), then update in an effect after hydration.
Predict#
Predict first
A component renders typeof window !== 'undefined' ? <MobileMenu/> : <DesktopMenu/>. What happens with SSR?
On the server window is undefined; in the browser it exists, so the first renders differ. Render one version first, then switch in an effect, or use CSS media queries. This check looks harmless, which is why it is so common.
Interview angle#
Say it like this — about 30 seconds
“Hydration makes server-rendered HTML interactive: React renders the same tree in the browser, reuses the existing DOM nodes and attaches event handlers. The first client render must match the server exactly. Mismatches come from dates and time zones, random ids, window or localStorage checks, invalid HTML nesting and browser extensions. I fix them by rendering the same output first and updating in an effect, or using useId for ids. suppressHydrationWarning is only for unavoidable text, such as a timestamp.”
Follow-up What is hydration? What causes hydration mismatches?
Follow-up When is suppressHydrationWarning acceptable?
Follow-up How does invalid HTML cause mismatches?
Practice#
Guided
Write a small version of React’s hydration check: find where two rendered trees first differ.
Done when
- Tag and text differences are reported at that node’s path.
- A different number of children is reported at the parent.
- Identical trees return null.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
What is hydration?
React attaching to server HTML by rendering in the browser and reusing the DOM.
Name three causes of hydration mismatches.
Dates or time zones, Math.random, typeof window checks (also extensions, invalid HTML).
How do you show browser-only content safely?
Render the same placeholder first, then update in an effect.
What does suppressHydrationWarning do?
Hides text mismatch warnings for one element; it does not fix them.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
useId for ids; format dates with a fixed time zone on both sides, or show them only after hydration.Check yourself: What happens to the server HTML in a part that mismatches?
React discards it and renders that part on the client.
How it works underneathSenior rounds
hydrateRoot walks the existing DOM while rendering and reuses each node that matches Source: React: hydrateRoot. In React 19, mismatch errors include a diff of the differing text.
Check yourself: Which API starts hydration?
hydrateRoot(container, element).
Edge cases and trapsWhere people slip
Extensions such as translators and password managers add attributes or nodes before React hydrates. React 19 skips many unexpected third-party additions in <head> and <body>, but content inside your app can still be affected.
Check yourself: Why might only some users see hydration errors?
Browser extensions or time zones change the HTML or the output on their machines.
In productionStaff-level answers
Check yourself: What is islands architecture?
Static HTML pages with small, separately hydrated interactive parts.
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- What is hydration? What causes hydration mismatches?