How to fix Hydration mismatch: the server-rendered page does not match the client in React

ReactINTERMEDIATEHIGHUpdated Dec 9, 2025ยท 184 views

This error occurs when Next.js server-side renders HTML that differs from what React produces during client-side hydration. Common causes include using browser APIs, dynamic dates/times, or non-deterministic values during the initial render. The fix involves ensuring consistent rendering between server and client.

Quick fix

Fixes Hydration mismatch: the server-rendered page does not match the client

# Example error output:
Warning: Text content did not match. Server: "Loading..." Client: "12/09/2025 3:45 PM"
  in div (at Component.tsx:12)
  1. Identify the specific element causing the mismatch
  2. Move browser API usage into useEffect hook
  3. Handle dynamic dates and times correctly
  4. Fix invalid HTML nesting
react โ€” error
# Example error output:
Warning: Text content did not match. Server: "Loading..." Client: "12/09/2025 3:45 PM"
in div (at Component.tsx:12)
Hydration mismatch: the server-rendered page does not match the client

What this error means

Next.js uses server-side rendering (SSR) to generate HTML on the server and send it to the browser. When the page loads, React performs "hydration" - attaching event listeners and taking over the static HTML to make it interactive. A hydration mismatch happens when the HTML structure, text content, or attributes generated on the server do not match what React tries to render on the client. React expects the initial client render to produce identical output to the server HTML. When they differ, React cannot properly hydrate the page, leading to this error. The mismatch can be caused by environment differences (server vs browser), timing differences, or non-deterministic code that produces different results on each run.

Typical symptoms

  • Console error "Hydration failed because the initial UI does not match what was rendered on the server"
  • Warning "Text content does not match server-rendered HTML"
  • Content flashing or changing immediately after page load
  • Event handlers not working or attaching to wrong elements
  • Visual flicker where content appears then disappears or changes
  • Form inputs losing focus or values after initial render
  • Random content differences between server HTML and client render
  • CSS styles appearing broken briefly then correcting themselves

Common causes

  1. Using browser-only APIs (window, document, localStorage, sessionStorage, navigator) during initial render without checking if they exist
  2. Rendering timestamps, dates, or times that differ between server and client due to timezone or execution timing differences
  3. Using Math.random() or other non-deterministic functions that produce different values on each render
  4. Third-party browser extensions or scripts modifying the DOM before React hydrates (ad blockers, accessibility tools, auto-translators)
  5. Invalid HTML nesting (div inside p tag, tr outside table, li outside ul/ol) causing browser to restructure the DOM
  6. Using conditional logic based on client-specific values unavailable during SSR (screen width, user agent, geolocation)
  7. Fetching different data on server versus client, causing structural differences in rendered HTML
  8. Using dynamic imports or lazy-loaded components without proper SSR configuration in Next.js

How to fix "Hydration mismatch: the server-rendered page does not match the client"

1Identify the specific element causing the mismatch

Open browser DevTools (F12) and check the console for the exact error message. Next.js usually shows which component and element is mismatched. Look for messages like "Warning: Expected server HTML to contain a matching <div> in <div>" or "Text content did not match". The error often includes the actual server content versus expected client content.

bash
# Example error output:
Warning: Text content did not match. Server: "Loading..." Client: "12/09/2025 3:45 PM"
  in div (at Component.tsx:12)
2Move browser API usage into useEffect hook

The most common cause is using browser-only APIs during render. Move any code accessing window, document, localStorage, or other browser APIs into a useEffect hook, which only runs on the client after hydration.

typescript
// WRONG - causes hydration mismatch
function WelcomeMessage() {
  const username = localStorage.getItem('username');
  return <div>Welcome {username}!</div>;
}

// CORRECT - server and client render the same initially
function WelcomeMessage() {
  const [username, setUsername] = useState<string | null>(null);
  
  useEffect(() => {
    setUsername(localStorage.getItem('username'));
  }, []);
  
  return <div>Welcome {username || 'Guest'}!</div>;
}
3Handle dynamic dates and times correctly

Date objects and timestamps generate different values on server versus client. Either format dates on the server and pass them as props, or defer date rendering until after hydration using useEffect.

typescript
// WRONG - server and client times will differ
function Timestamp() {
  return <div>Page loaded at {new Date().toLocaleString()}</div>;
}

// CORRECT - use useEffect to update after hydration
function Timestamp() {
  const [timestamp, setTimestamp] = useState<string>('')
  
  useEffect(() => {
    setTimestamp(new Date().toLocaleString());
  }, []);
  
  return <div>{timestamp ? `Page loaded at ${timestamp}` : 'Loading...'}</div>;
}

// ALTERNATIVE - pass formatted date from server
export async function getServerSideProps() {
  return {
    props: {
      serverTime: new Date().toISOString()
    }
  };
}
4Fix invalid HTML nesting

Browsers automatically fix invalid HTML nesting, which causes the actual DOM to differ from what React expects. Check that you are not nesting invalid elements.

typescript
// WRONG - div cannot be inside p
<p>
  <div>Content</div>
</p>

// WRONG - button cannot be inside button
<button>
  <button>Click me</button>
</button>

// CORRECT - use valid nesting
<div>
  <div>Content</div>
</div>

// For styled text, use span inside p
<p>
  <span className="highlight">Content</span>
</p>
5Use suppressHydrationWarning for unavoidable mismatches

For specific elements where a mismatch is intentional and unavoidable (like showing server-generated timestamps), add suppressHydrationWarning to suppress the warning. Only use this as a last resort for non-critical content.

typescript
<div suppressHydrationWarning>
  Rendered on server at {new Date().toISOString()}
</div>
6Disable SSR for problematic components

If a component cannot be made compatible with SSR, use Next.js dynamic imports with ssr: false to render it only on the client side.

typescript
import dynamic from 'next/dynamic';

// Component will only render on client, preventing hydration issues
const ClientOnlyComponent = dynamic(
  () => import('../components/ClientOnlyComponent'),
  { ssr: false }
);

export default function Page() {
  return (
    <div>
      <h1>My Page</h1>
      <ClientOnlyComponent />
    </div>
  );
}
7Ensure consistent data between server and client

Make sure both server and client use the same data for initial render. Use getServerSideProps, getStaticProps, or Server Components to fetch data once and pass it down.

typescript
// pages/posts/[id].tsx
export async function getServerSideProps({ params }) {
  const post = await fetchPost(params.id);
  return { props: { post } };
}

export default function Post({ post }) {
  // Both server and client receive same post data
  return <article>{post.content}</article>;
}
8Test in production mode

Hydration issues may not appear in development mode. Build and run your app in production mode to catch these errors before deployment.

bash
npm run build
npm run start
# Visit your app and check browser console for hydration errors

Advanced notes

Next.js 13+ with the App Router provides better error messages for hydration mismatches compared to the Pages Router, often showing you the exact component and line number. In the App Router, Server Components do not hydrate at all - only Client Components (marked with "use client") undergo hydration. This architectural difference can help reduce hydration issues by moving server-only logic entirely to Server Components. For debugging difficult cases, use React DevTools browser extension to inspect component trees and compare server versus client renders. Some third-party libraries designed for browser-only use (charts, maps, rich text editors) may require wrapping in dynamic imports with ssr: false. Consider using the next/dynamic loading component with a custom loading placeholder to improve user experience while client-only components load. In rare cases, browser extensions like ad blockers or translation tools can modify the DOM before React hydrates, causing mismatches - test in incognito mode if issues persist.

Frequently asked questions

What does "Hydration mismatch: the server-rendered page does not match the client" mean?
js uses server-side rendering (SSR) to generate HTML on the server and send it to the browser. When the page loads, React performs "hydration" - attaching event listeners and taking over the static HTML to make it interactive. A hydration mismatch happens when the HTML structure, text content, or attributes generated on the server do not match what React tries to render on the client.
How do I fix "Hydration mismatch: the server-rendered page does not match the client"?
This error occurs when Next.js server-side renders HTML that differs from what React produces during client-side hydration. Common causes include using browser APIs, dynamic dates/times, or non-deterministic values during the initial render. The fix involves ensuring consistent rendering between server and client.
What causes "Hydration mismatch: the server-rendered page does not match the client"?
Using browser-only APIs (window, document, localStorage, sessionStorage, navigator) during initial render without checking if they exist Rendering timestamps, dates, or times that differ between server and client due to timezone or execution timing differences Using Math.random() or other non-deterministic functions that produce different values on each render
Is the "Hydration mismatch: the server-rendered page does not match the client" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading