DEV Community

Cover image for Hydration Errors in ReactJS and NextJS: What, Why, and How to Fix Them
Rahul Giri
Rahul Giri

Posted on

Hydration Errors in ReactJS and NextJS: What, Why, and How to Fix Them

Intro:
If your Next.js or React app has ever thrown an alarming warning like this in the console:

Warning: Text content did not match. Server: "Hello" Client: "Hello!"
Enter fullscreen mode Exit fullscreen mode

Don’t worry — you didn’t break the internet.

Hydration errors are common (and often confusing) in server-rendered React apps like those built with Next.js. In this post, we'll walk through exactly what hydration is, why it breaks, how to intentionally reproduce a hydration error, and most importantly — how to avoid it.


What is Hydration?

When using Server-Side Rendering (SSR) or Static Site Generation (SSG), your React app first sends pre-rendered HTML from the server to the browser. Then, once the JavaScript bundle loads on the client, React “hydrates” the app by attaching event listeners, restoring state, and connecting to that HTML.

In simple terms:

  • The server sends a body (the HTML).
  • The browser installs the brain (React JS).
  • If the body and brain don’t match, React freaks out.

What Happens During Hydration?

Here’s the actual step-by-step breakdown of hydration:

  1. Pre-rendered HTML from server arrives
    This is visible in “View Page Source” — it lives in the real DOM.

  2. React loads on the client
    It rebuilds the virtual DOM based on components, props, and logic.

  3. React compares real DOM (from server) with virtual DOM (from client)
    If everything matches — success!
    If not — hydration warning or full failure.

  4. React attaches logic
    Once matched, React wires up event listeners, useEffect, and more — without re-rendering.


Why Does Hydration Fail?

Hydration fails if the HTML structure or content rendered on the server differs from what React generates on the client during hydration.

Here are some common culprits:

  • Using Math.random() in JSX
  • Using new Date() or Date.now() directly in render
  • Accessing browser-only APIs like window or document during SSR
  • Conditional rendering based on client-only logic
  • Invalid HTML nesting like <p><h2></h2></p>

Let’s Reproduce a Hydration Error (on purpose)

Want to demo this in your own Next.js project? Here are three guaranteed ways to trigger a hydration error.


1. Using Math.random()

export default function Page() {
  return (
    <div>
      <h1>Random Number</h1>
      <p>{Math.random()}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why it fails: The server renders one random number, the client renders another. They don’t match → hydration warning.


2. Using new Date().toString()

export default function Page() {
  return (
    <div>
      <h1>Current Time</h1>
      <p>{new Date().toString()}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why it fails: The date string is different on server vs client → mismatch → hydration error.


3. Invalid HTML nesting

export default function Page() {
  return (
    <p>
      <h2>This will break</h2>
    </p>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why it fails: React’s DOM nesting rules prevent <h2> inside <p>. The browser may fix the HTML automatically, but React’s virtual DOM won’t know — and hydration fails.


How to Avoid Hydration Errors

Here’s your checklist:

  • Don’t use non-deterministic values like Math.random() or Date.now() directly in JSX
  • Don’t access browser-only variables like window or localStorage during SSR
  • Use useEffect() for browser-only logic (runs only on the client)
  • Wrap client-only components with 'use client' directive in Next.js App Router
  • Keep your JSX structurally valid (avoid illegal nesting)

Mental Model

Think of hydration like this:

The server gives you a human body (HTML). The client loads a brain (React). If a hand is where the ear should be, the brain can’t connect — it panics.

That’s a hydration error.


Bonus: Debugging Tips

  • Always check DevTools console — most hydration issues show up as warnings
  • Disable JavaScript and “View Page Source” to inspect server-rendered HTML
  • Use React DevTools to explore the component tree and spot mismatches

Conclusion

Hydration errors can be confusing at first, but once you get the mental model — HTML from server, JavaScript on client, both must match — it becomes much easier to debug and avoid them.

Stay hydrated, keep your body and brain in sync, and may your React apps always load in peace.

If you enjoyed this post, follow me for more practical React/Next.js tips and dev-friendly breakdowns. You can also reach out if you want me to turn this into a visual explainer or animation!

Top comments (0)