What Is Hydration in React: How Server-Rendered Pages Become Interactive

What Is Hydration in React?

Hydration in React is the process where React takes over a static HTML page that was already rendered on the server and “attaches” interactivity to it on the client side. In simple words: the server sends a fully painted picture of your UI, and React adds the wires, buttons, and event listeners once the JavaScript loads in the browser.

If you have ever used Next.js, Remix, or Gatsby, you have already shipped hydrated React apps, even if you did not know it. This guide breaks down hydration in plain English, with diagrams in words, real code, and the typical errors that drive developers crazy.

react code laptop

The Problem Hydration Solves

To understand hydration, you first need to picture two ways a React app can be delivered:

  • Client-Side Rendering (CSR): The browser downloads an almost empty HTML file, then JavaScript builds everything. Users see a blank page until JS is ready.
  • Server-Side Rendering (SSR): The server pre-renders the HTML and sends it ready to display. Users see content instantly, but it is not yet interactive.

SSR is great for performance and SEO, but there is a catch: the HTML is just a screenshot. Buttons do not click, forms do not submit, state does not update. That is where hydration steps in.

Hydration in Words: A Simple Diagram

[Server]                      [Browser]
   |                             |
   |--- Renders HTML ----------->|  (User sees UI immediately)
   |                             |
   |--- Sends JS bundle -------->|
   |                             |
   |                          React boots
   |                             |
   |                          Walks existing DOM
   |                             |
   |                          Attaches event listeners
   |                             |
   |                          App is now INTERACTIVE

Think of the server-rendered HTML as a dry sponge. Hydration is the water (JavaScript) that brings it to life. That metaphor is exactly why it is called hydration.

react code laptop

How Hydration Works Under the Hood

Since React 18, hydration is handled by the hydrateRoot API. Instead of creating new DOM nodes, React walks through the existing markup and matches it node by node with your React component tree.

Here is a minimal example:

// Server (Node.js)
import { renderToString } from 'react-dom/server';
import App from './App';

const html = renderToString(<App />);
res.send(`<!DOCTYPE html><div id="root">${html}</div><script src="/bundle.js"></script>`);
// Client (browser)
import { hydrateRoot } from 'react-dom/client';
import App from './App';

hydrateRoot(document.getElementById('root'), <App />);

During this step, React:

  1. Reads the existing DOM produced by the server.
  2. Builds the virtual DOM from your components.
  3. Compares them node by node (this must match exactly).
  4. Attaches event handlers like onClick, onChange, and state hooks.

Why Hydration Matters for Next.js and Other SSR Frameworks

Frameworks like Next.js rely on hydration to give you the best of both worlds: fast initial paint and a fully reactive app. Without hydration, server rendering would just be static HTML, no different from a 1998 website.

Approach First Paint Interactive SEO
CSR (plain React) Slow After JS loads Weak
SSR + Hydration Fast After hydration Strong
RSC (React Server Components) Fast Selective hydration Strong

In 2026, with React Server Components and selective hydration becoming the default in Next.js App Router projects, hydration is smarter: only the interactive parts of the tree get hydrated. Static content stays static, saving bandwidth and CPU.

react code laptop

The Famous Hydration Mismatch Error

If you have ever seen this in your console, welcome to the club:

Hydration failed because the initial UI does not match what was rendered on the server.

This happens when the HTML produced on the server does not match what React tries to render on the client. React expects pixel-perfect agreement during the matching phase.

Common Causes of Hydration Mismatches

  • Using Date.now(), Math.random(), or new Date() directly in render.
  • Reading window, localStorage, or navigator during render (these do not exist on the server).
  • Conditionally rendering based on user locale or timezone.
  • Invalid HTML nesting like a <div> inside a <p>.
  • Browser extensions injecting attributes into your HTML.

Example of a Buggy Component

function Greeting() {
  const hour = new Date().getHours(); // different on server vs client
  return <p>{hour < 12 ? 'Good morning' : 'Good afternoon'}</p>;
}

The server may render “Good morning” while the client renders “Good afternoon” depending on timing or timezone. Boom, hydration mismatch.

How to Fix It

Move time-sensitive or browser-only logic into useEffect, which only runs on the client after hydration:

function Greeting() {
  const [greeting, setGreeting] = useState('Hello');

  useEffect(() => {
    const hour = new Date().getHours();
    setGreeting(hour < 12 ? 'Good morning' : 'Good afternoon');
  }, []);

  return <p>{greeting}</p>;
}

Other useful techniques:

  1. Use the suppressHydrationWarning prop for known dynamic content like timestamps.
  2. Wrap browser-only components in a <ClientOnly> wrapper.
  3. In Next.js, mark components with 'use client' only when needed.
  4. Use next/dynamic with ssr: false for libraries that touch the DOM directly.

Selective and Partial Hydration: The Modern Evolution

Traditional hydration walks the entire tree, even parts that will never become interactive. That is wasteful. Modern React introduces smarter strategies:

  • Selective Hydration: React 18+ can hydrate parts of the page out of order, prioritizing what the user interacts with first.
  • Partial Hydration: Only “islands” of interactivity get hydrated. The rest stays as plain HTML.
  • Progressive Hydration: Components are hydrated as they enter the viewport or as the user interacts with them.

These patterns are the backbone of frameworks like Next.js App Router, Astro, and Qwik (which goes even further with “resumability”).

react code laptop

Quick Checklist Before Shipping SSR React

  • Never read window or document in the render body.
  • Validate your HTML nesting structure.
  • Use useEffect for time, random values, and browser APIs.
  • Test with JavaScript disabled to confirm the server output looks correct.
  • Watch the browser console for hydration warnings in development.

FAQ

What does hydration mean in React in one sentence?

Hydration is the process of taking server-rendered HTML and attaching React’s JavaScript event listeners and state to it, making the page interactive.

Is hydration the same as rendering?

No. Rendering creates the DOM. Hydration reuses an existing DOM and only adds interactivity on top of it.

Why do hydration errors happen?

They occur when the HTML produced on the server does not match what React would render on the client. The most common cause is using browser-only APIs or non-deterministic values like Date.now() inside components.

Does Next.js use hydration?

Yes. Next.js relies on hydration for its Pages Router and uses selective hydration combined with React Server Components in the App Router.

Can I disable hydration?

You can avoid hydration for specific components by lazy-loading them client-only (for example with next/dynamic and ssr: false) or by using static export with no client JavaScript.

What is the difference between hydrate and hydrateRoot?

hydrate was the legacy API used before React 18. hydrateRoot is the modern replacement and enables concurrent features like selective hydration.

Final Thoughts

Hydration is the secret handshake between server and browser. It is what makes your Next.js pages feel instant and fully interactive. Once you understand that React expects the server HTML and the client render to match exactly, most hydration bugs become easy to spot and fix.

Master hydration and you master modern React. Your Core Web Vitals, SEO, and users will all thank you.