🔄 Understanding Hydration in Next.js (And Why Hydration Errors Happen)


When building with Next.js, hydration errors can be tricky, especially when they pop up only in development mode. This blog post explains:
What hydration means
Why hydration errors occur
Common causes
Best practices to avoid them
Let’s break it down 👇
💧 What is Hydration?
Hydration is the process of attaching JavaScript behaviour(interactivity) to static HTML generated by the server.
When you build a Next.js app, pages are pre-rendered on the server and sent to the client as static HTML. Once the browser loads this HTML, React "hydrates" it—i.e., binds event listeners and makes the page interactive.
Hydration is the process of turning static server-rendered HTML into a fully interactive React application in the browser.
Here's a quick diagram:
Server Rendering ➜ Static HTML ➜ [Browser Loads Page]
⬇
React attaches JS logic
⬇
✅ Hydration Complete
When hydration works:
You get fast load times (from server-rendering)
And dynamic interactivity (from React)
⚠️ What Are Hydration Errors?
A hydration error means:
"React tried to hydrate the page but the HTML from the server doesn’t match what the client rendered."
Example warning:
Warning: Text content did not match. Server: "164725..." Client: "164733..."
This happens when the HTML on the client and server is different, and React can't safely reuse it.
🧨 Common Causes of Hydration Errors
1. ❌ Using Date.now()
or Math.random()
in Render
// ❌ Bad: Generates different values on server and client
export default function Page() {
const now = Date.now();
return <div>Current time: {now}</div>;
}
✅ Fix with useEffect
:
// ✅ Safe: Runs only on client
import { useEffect, useState } from 'react';
export default function Page() {
const [now, setNow] = useState(null);
useEffect(() => {
setNow(Date.now());
}, []);
return <div>Current time: {now}</div>;
}
2. ❌ Client-Only Logic (e.g., window
, geolocation)
// ❌ This will throw during SSR
const isMobile = window.innerWidth < 768;
✅ Fix:
import { useEffect, useState } from 'react';
export default function ResponsiveComponent() {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
setIsMobile(window.innerWidth < 768);
}, []);
return <div>{isMobile ? "Mobile view" : "Desktop view"}</div>;
}
3. ❌ Browser Extensions Causing Unexpected DOM Changes
Some extensions like Grammarly, Adblock, etc., can modify HTML in the DOM before hydration.
✅ Fix: Ignore these in dev. They don’t usually affect your production app.
🔧 Best Practices to Avoid Hydration Errors
Do ✅ | Avoid ❌ |
Use useEffect for client-only code | Calling Date.now() or Math.random() in render |
Dynamically load client-only components | Using window , localStorage , or navigator during SSR |
Use dynamic(import, { ssr: false }) | Relying on values that differ server/client |
Example: Dynamic import for client-only components
import dynamic from "next/dynamic";
const NoSSRComponent = dynamic(() => import("./MyComponent"), {
ssr: false,
});
export default function Page() {
return <NoSSRComponent />;
}
🧠 Wrap-Up
Hydration is what makes React apps feel dynamic and fast, especially in Next.js with server-side rendering. But hydration errors can creep in when:
Values mismatch across server and client
You use non-deterministic values in render
Browser plugins interfere
🎯 Remember:
Fix these errors in development.
They won’t show in production, but the underlying bug might still affect UX.
✅ Visual Summary
Correct SSR: ❌ Bad Hydration:
[Server HTML: 100] [Server HTML: 100]
[Client HTML: 100] [Client HTML: 200]
✅ No Error ⚠️ Hydration Mismatch
💬 Questions?
Have a tricky hydration error you can’t resolve? Tweet at @shanutiwari1010 or drop a comment below!
Happy coding! 🚀
Subscribe to my newsletter
Read articles from Shanu Tiwari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Shanu Tiwari
Shanu Tiwari
I'm Shanu Tiwari, a passionate front-end software engineer. I'm driven by the power of technology to create innovative solutions and improve user experiences. Through my studies and personal projects, I have developed a strong foundation in programming languages such as Javascript and TypeScript, as well as a solid understanding of software development methodologies.