← Back to all articles

How to Fix React Hydration Mismatch Errors

August 26, 2026By Kazi Samiul Haque Adrik

What is a React Hydration Error?

If you've built applications using Next.js, Remix, or any Server-Side Rendered (SSR) React framework, you have likely encountered this terrifying console error:

Warning: Text content did not match. Server: "X" Client: "Y"

This is called a Hydration Mismatch Error. When a user visits your SSR application, the server generates and sends static HTML. Once the browser downloads the JavaScript, React attempts to "hydrate" or attach event listeners to that HTML. If the initial HTML generated by the server does not exactly match the initial HTML generated by the client on its first render pass, React throws this error and forcefully discards the server HTML, ruining the performance benefits of SSR.

Here are the most common causes of hydration errors and exactly how to fix them.

Cause 1: Browser Extensions Modifying the DOM

The absolute most common cause of hydration errors in development mode is browser extensions. Extensions like Grammarly, LastPass, or Dark Reader automatically inject custom HTML attributes (like data-gr-ext-installed) or entire nested <div>s into your <body> tag.

Because the server didn't generate those elements, React freaks out when it tries to hydrate.

The Fix: Next.js provides a built-in escape hatch for this. Add the suppressHydrationWarning attribute to your main <html> or <body> tag in your root layout.

// src/app/layout.js
export default function RootLayout({ children }) {
  return (
    // suppressHydrationWarning prevents errors caused by browser extensions
    <html lang="en" suppressHydrationWarning> 
      <body>
        {children}
      </body>
    </html>
  );
}

Note: This only suppresses mismatch warnings one level deep. It is perfectly safe to use on the <html> and <body> tags.

Cause 2: Improper Date and Time Formatting

If you generate a timestamp using new Date().toLocaleTimeString() inside a server component, the server will format it using UTC time (or the server's local timezone). When the client hydrates the page, it uses the user's local timezone (e.g., EST or PST).

Server: 12:00 PM Client: 07:00 AM Result: Hydration Error.

The Fix: Only render timezone-dependent dates on the client after the initial mount, using a custom hook, or format everything strictly in UTC on both sides.

import { useEffect, useState } from 'react';

export default function Clock() {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return <span>Loading time...</span>; // Rendered on Server and first Client pass
  }

  // Safe to render user's local time because it happens AFTER hydration
  return <span>{new Date().toLocaleTimeString()}</span>; 
}

Cause 3: Invalid HTML Nesting

React uses the browser's native DOM parser. If you accidentally write invalid HTML, the browser will try to auto-correct it before React hydrates.

For example, nesting a <p> tag inside another <p> tag is illegal in HTML.

// ILLEGAL: 
<p>This is a paragraph. <p>This is illegal nesting.</p></p>

The server sends it exactly like that. But the browser auto-corrects it to:

<p>This is a paragraph.</p><p>This is illegal nesting.</p><p></p>

When React checks the tree, it doesn't match!

The Fix: Always write semantically valid HTML. Use a linter like eslint-plugin-jsx-a11y and remember:

  • Never put block elements (<div>, <h1>, <p>) inside inline elements (<span>, <a>).
  • Never nest <p> tags.
  • Never nest <a> tags.

Conclusion

Hydration errors seem scary, but they are incredibly logical once you understand the server-client rendering lifecycle. By suppressing browser extensions at the root, managing client-side state correctly, and writing valid HTML, you can eliminate 99% of hydration mismatches in your Next.js apps.

Available for projects
Bangladesh
SSC '26 Grad