How to fix How to fix "Hydration mismatch" in React in React

ReactINTERMEDIATEHIGHUpdated Dec 8, 2025· 165 views

A hydration mismatch occurs when the HTML rendered on the server differs from what React renders on the client during hydration. This causes React to fail to properly attach to existing markup and can lead to missing event listeners, state inconsistencies, and unexpected behavior. Understanding the root cause and using the right solution prevents this critical SSR issue.

Quick fix

Fixes How to fix "Hydration mismatch" in React

// WRONG - renders differently on server vs client
export function TimeComponent() {
  const isClient = typeof window !== "undefined";
  return <div>{isClient ? new Date().toLocaleString() : "Loading..."}</div>;
}

// CORRECT - server and client match, then useEffect updates
export function TimeComponent() {
  const [time, setTime] = useState<string>("Loading...");
  
  useEffect(() => {
    setTime(new Date().toLocaleString());
  }, []);
  
  return <div>{time}</div>;
}
  1. Check the browser console for the exact hydration error message
  2. Move browser-only code into useEffect
  3. Use suppressHydrationWarning as a temporary fix only
  4. Implement two-pass rendering for intentional differences
react — error
// WRONG - renders differently on server vs client
export function TimeComponent() {
const isClient = typeof window !== "undefined";
return <div>{isClient ? new Date().toLocaleString() : "Loading..."}</div>;
}
// CORRECT - server and client match, then useEffect updates
export function TimeComponent() {
const [time, setTime] = useState<string>("Loading...");
useEffect(() => {
setTime(new Date().toLocaleString());
}, []);
return <div>{time}</div>;
}

What this error means

In server-side rendering (SSR), React first renders your app on the server and sends HTML to the browser. When the browser loads, React "hydrates" this HTML by attaching event listeners and taking over rendering. A hydration mismatch occurs when the server-rendered HTML does not match what React expects to render on the client. This can happen because the two environments render different content, use different data, or execute different code paths. React detects the mismatch and throws a warning, indicating a serious synchronization problem between server and client rendering. In the best case, this causes a slowdown or visual flicker; in the worst case, event handlers attach to the wrong DOM elements, leading to broken interactions.

Typical symptoms

  • Console warnings like "Hydration failed because the initial UI does not match what was rendered on the server"
  • Content appearing briefly then changing or disappearing when the page loads
  • Event handlers not responding or responding on the wrong elements
  • CSS styling flashing or changing after page load (Flash of Unstyled Content)
  • Form inputs losing focus or values after hydration completes
  • Random content differences between what you see during page load and after JavaScript executes
  • Browser console showing React warnings about mismatched HTML structure or text content

Common causes

  1. Using browser-only APIs like window, document, or localStorage during initial render without checking if they exist on the server
  2. Rendering different content based on Math.random() or other non-deterministic values that differ between server and client
  3. Fetching different data on the server versus the client, causing the rendered HTML structure to differ
  4. Using conditional renders that depend on client-specific values (like user timezone, device type, or browser features) that are not available during server rendering
  5. Third-party scripts modifying the DOM before React hydrates (like iOS Safari converting phone numbers to clickable links)
  6. Using dynamic imports or lazy-loaded components without proper SSR handling
  7. Time-dependent values like timestamps, dates, or time-based conditionals rendering different content on server versus client
  8. Incorrect setup of streaming responses or partial hydration in frameworks like Next.js

How to fix this error

1Check the browser console for the exact hydration error message

Open your browser's developer tools (F12) and look for red errors or yellow warnings mentioning "hydration". The error message usually indicates which element or text content is mismatched. Note the specific element name and the values that differ.

2Move browser-only code into useEffect

Identify any code that accesses browser APIs like window, document, localStorage, or navigator. Move this code into a useEffect hook. useEffect only runs on the client after hydration completes, ensuring the server and client render the same initial HTML.

typescript
// WRONG - renders differently on server vs client
export function TimeComponent() {
  const isClient = typeof window !== "undefined";
  return <div>{isClient ? new Date().toLocaleString() : "Loading..."}</div>;
}

// CORRECT - server and client match, then useEffect updates
export function TimeComponent() {
  const [time, setTime] = useState<string>("Loading...");
  
  useEffect(() => {
    setTime(new Date().toLocaleString());
  }, []);
  
  return <div>{time}</div>;
}
3Use suppressHydrationWarning as a temporary fix only

If you have a small element where a mismatch is unavoidable (like a dynamic timestamp), you can add suppressHydrationWarning={true} to that specific element. This silences the warning but does not fix the underlying issue. Use this only as a last resort for non-critical content.

typescript
<div suppressHydrationWarning>
  Generated at {new Date().toISOString()}
</div>
4Implement two-pass rendering for intentional differences

If you intentionally need to render different content on server versus client, use state to track whether you're on the client. On the first render, output server content; then useEffect updates to client content. React will not complain about the initial match.

typescript
export function ClientOnlyFeature() {
  const [isClient, setIsClient] = useState(false);
  
  useEffect(() => {
    setIsClient(true);
  }, []);
  
  return (
    <div>
      {isClient ? (
        <ClientSpecificContent />
      ) : (
        <ServerSafeContent />
      )}
    </div>
  );
}
5Ensure data fetching is consistent between server and client

If you fetch data during rendering, ensure the same data is available on both server and client. For Next.js, use getServerSideProps or getStaticProps to fetch data at build/request time and pass it as props. For other frameworks, fetch on the server and embed the data in the initial HTML so the client uses the same data.

typescript
// Next.js example
export async function getServerSideProps() {
  const data = await fetchData();
  return { props: { data } };
}

export default function Page({ data }) {
  // Both server and client receive the same data
  return <div>{data.title}</div>;
}
6Disable SSR for problematic components using dynamic imports

If a component cannot be fixed and always causes hydration mismatches, you can dynamically import it with SSR disabled (in Next.js). This prevents the server from rendering it, so no mismatch occurs.

typescript
import dynamic from "next/dynamic";

const ProblematicComponent = dynamic(
  () => import("./ProblematicComponent"),
  { ssr: false }
);

export default function Page() {
  return <ProblematicComponent />;
}
7Test server and client rendering separately

Build and run your production build locally to catch hydration issues before deployment. In Next.js, run npm run build && npm run start. Use browser DevTools to inspect the actual HTML sent by the server (View Page Source) and compare it to what React tries to render on the client. Use React Developer Tools browser extension to inspect component render output.

Advanced notes

Hydration mismatches are particularly common in Next.js applications because Next.js uses SSR by default. When debugging, understand that React compares the server HTML byte-by-byte with the client render output. Even whitespace differences can cause mismatches in some cases. For complex applications with many dynamic features, consider using frameworks like Next.js that provide built-in solutions like getServerSideProps and getStaticProps. In some cases, iOS Safari automatically converts phone numbers and email addresses in text content into clickable links, which can cause unexpected hydration mismatches. If you cannot find the source of a mismatch, try using React.StrictMode during development, which highlights potential issues. For performance-critical applications, consider using partial hydration or progressive hydration strategies that hydrate only critical components first.

Frequently asked questions

What does "How to fix "Hydration mismatch" in React" mean?
In server-side rendering (SSR), React first renders your app on the server and sends HTML to the browser. When the browser loads, React "hydrates" this HTML by attaching event listeners and taking over rendering. A hydration mismatch occurs when the server-rendered HTML does not match what React expects to render on the client.
How do I fix "How to fix "Hydration mismatch" in React"?
A hydration mismatch occurs when the HTML rendered on the server differs from what React renders on the client during hydration. This causes React to fail to properly attach to existing markup and can lead to missing event listeners, state inconsistencies, and unexpected behavior. Understanding the root cause and using the right solution prevents this critical SSR issue.
What causes "How to fix "Hydration mismatch" in React"?
Using browser-only APIs like window, document, or localStorage during initial render without checking if they exist on the server Rendering different content based on Math.random() or other non-deterministic values that differ between server and client Fetching different data on the server versus the client, causing the rendered HTML structure to differ
Is the "How to fix "Hydration mismatch" in React" 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