Hydration Proof

Search documentation

Find a page or section

What is hydration in React?

The server sends HTML. React in the browser adopts it instead of drawing the page again.

What is hydration in React? The server sends a page as HTML. React then runs in the browser, connects to that HTML, and makes it interactive. The page can appear before JavaScript finishes loading; hydration makes its buttons and other controls work.

What is hydration in React, step by step

For React hydration, SSR happens first. Then the browser takes over:

  1. The server renders your React components to HTML.
  2. The browser displays the HTML. You can see the content, but React event handlers are not attached yet.
  3. The JavaScript loads, and React renders the same component tree in the browser.
  4. React matches that tree to the HTML already on the page and attaches event handlers.
  5. The page is interactive. Later updates work as they would in any React app.

For step 4 to work, the first browser render must match the server HTML. See the hydrateRoot reference.

React hydration explained in code

Frameworks call hydrateRoot for you. If you manage server rendering yourself, the browser entry can look like this:

src/entry.client.tsx
import { hydrateRoot } from "react-dom/client";
import { App } from "./App";
 
// The server already rendered <App /> into #root.
hydrateRoot(document.getElementById("root")!, <App />, {
  // Called when React recovers from an error, including a hydration mismatch.
  onRecoverableError(error, errorInfo) {
    console.error(error, errorInfo.componentStack);
  },
});

The hydrateRoot React API receives the existing DOM node and the React tree that produced it. You can also pass options such as onRecoverableError to log problems. If you set identifierPrefix for useId, use the same prefix on the server and in the browser. Older examples call it ReactDOM.hydrateRoot; import it from react-dom/client instead.

hydrateRoot vs createRoot

hydrateRootcreateRoot
Starts fromHTML the server renderedAn empty DOM node
First renderAdopts existing DOM nodesCreates every DOM node
NeedsThe same output on server and clientNothing from the server
When the output differsA hydration errorNot applicable

Use createRoot when the server did not render the React tree. Use hydrateRoot when it did. hydration-proof marks a page mounted with createRoot as HP9003 for information: there is no server-rendered React tree to compare.

Hydration mismatch: meaning and consequences

A hydration mismatch means the first browser render does not match the server HTML. The difference might be text, an attribute, or an element. Fix the difference in the component rather than hiding the warning.

The result depends on your React version and whether you are running a development or production build:

  • Text or structure differs in React 19: React renders the affected tree again in the browser. If there is no containing Suspense boundary, it may render the whole root again. Development shows a diff; production may show error #418.
  • An attribute differs in React 19: React may leave the server attribute in place. Development warns, but production may not report it.
  • React 18: Development shows hydration warnings. Production can show minified errors #418, #423, or #425.

See the React hydration error guide for causes and fixes, or look up a specific message in errors.

What is hydration in web development?

In web development more broadly, hydration means making server-rendered HTML interactive in the browser. With client-only rendering, the browser builds the page from JavaScript instead of taking over an existing page.

Server HTML lets people and crawlers see content before the client app is ready. The tradeoff is that server and browser output must agree. Astro can hydrate individual React islands according to their client:* directives.

What is hydration in Next.js?

Next.js handles hydration for you. The router determines which components run in the browser:

  • Pages Router: the whole page is a client component tree. It is rendered on the server and hydrated in the browser.
  • App Router: Server Components render only on the server. Client Components, the files marked "use client", are also prerendered to HTML on the server and then hydrated. "use client" does not mean "client only".

A Client Component can still render on the server. If it reads window, localStorage, or the current time during render, its first browser output may differ. See Next.js hydration errors.

Do Server Components hydrate?

For React Server Components, hydration applies only to their Client Component children. Server Component code does not run in the browser; the browser receives its rendered output.

Its HTML still has to be valid. For example, a <div> inside a <p> can break hydration regardless of which component produced it.

Streaming and selective hydration

Streaming sends the page in pieces. The initial shell arrives first; content inside a Suspense boundary can arrive later. React hydrates each part when its HTML and code are ready, and can prioritize a boundary the user interacts with.

A Suspense boundary can also contain a mismatch. If hydration fails inside one, React can render that boundary again instead of the whole page. hydration-proof reports these cases as HP1010 and HP1011. See how it works.

Check that your pages hydrate

To check your pages, install hydration-proof and run a test:

npm install -D hydration-proof
npx hydration-proof install
npx hydration-proof test

The quick start walks through the first report.