How to fix How to fix "Hydration mismatch" in React 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.
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>;
}- Check the browser console for the exact hydration error message
- Move browser-only code into useEffect
- Use suppressHydrationWarning as a temporary fix only
- Implement two-pass rendering for intentional differences
// WRONG - renders differently on server vs clientexport function TimeComponent() {const isClient = typeof window !== "undefined";return <div>{isClient ? new Date().toLocaleString() : "Loading..."}</div>;}// CORRECT - server and client match, then useEffect updatesexport 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
- 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
- Using conditional renders that depend on client-specific values (like user timezone, device type, or browser features) that are not available during server rendering
- Third-party scripts modifying the DOM before React hydrates (like iOS Safari converting phone numbers to clickable links)
- Using dynamic imports or lazy-loaded components without proper SSR handling
- Time-dependent values like timestamps, dates, or time-based conditionals rendering different content on server versus client
- Incorrect setup of streaming responses or partial hydration in frameworks like Next.js
How to fix this error
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.
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.
// 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>;
}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.
<div suppressHydrationWarning>
Generated at {new Date().toISOString()}
</div>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.
export function ClientOnlyFeature() {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return (
<div>
{isClient ? (
<ClientSpecificContent />
) : (
<ServerSafeContent />
)}
</div>
);
}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.
// 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>;
}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.
import dynamic from "next/dynamic";
const ProblematicComponent = dynamic(
() => import("./ProblematicComponent"),
{ ssr: false }
);
export default function Page() {
return <ProblematicComponent />;
}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
- 📚React Official Documentation
- 📖React hydrateRoot API documentation(Official Docs)
- 📖Next.js official hydration error guide(Official Docs)
- 📝
- 📝