What is Hydration in Next.js ⚠️?


When you use Next.js, the page render twice:

  1. On the Server Side (SSR) :- In this process HTML is generated.
  2. On the Client (Browser):- React hydrates that HTML and attaches the event listeners.
    Think of hydration as: “React wakes up the static HTML and converts it into an interactive app.”
    For hydration to work, the HTML that the server generates must match the HTML that React generates in the browser.

If they don’t match → Next.js throws a hydration error.

Eg:- Server generated HTML = A
Browser generated HTML = B
React is confused
Hydration breaks



Reason – Why Does This Happen?

1.Using browser-only APIs during SSR:-
Server → window doesn’t exist → error
Client → window exists → mismatch

const width = window.innerWidth;
Enter fullscreen mode

Exit fullscreen mode

2.Using Date, Math.random(), or dynamic values during render:- Server timestamp ≠ client timestamp → mismatch.

<p>{Date.now()}</p>
Enter fullscreen mode

Exit fullscreen mode

3.Conditionally rendering components differently on server vs client:-
Server → window undefined → renders nothing
Client → window exists → renders sidebar
Mismatch → hydration error.

{typeof window !== "undefined" && <Sidebar />}
Enter fullscreen mode

Exit fullscreen mode

4.Fetching data differently on server and client:- You might accidentally:

  • Fetch server-side once
  • Fetch client-side again with a different result
    This changes HTML → mismatch.



How to Fix Hydration Issues?

1.Wrap client-only code inside useEffect:- Anything using window, document, localStorage:

const [width, setWidth] = useState(null);
useEffect(() => {
  setWidth(window.innerWidth);
}, []);
Enter fullscreen mode

Exit fullscreen mode

Server renders nothing → client fills it later.

2.Avoid Date.now() or Math.random() directly in render:- Use useEffect or calculate once.

const [time, setTime] = useState(null);
useEffect(() => setTime(Date.now()), []);
Enter fullscreen mode

Exit fullscreen mode

3.Use dynamic import for client-only components:- Example: charts, maps, heavy UI.

const Chart = dynamic(() => import("../Chart"), { ssr: false });
Enter fullscreen mode

Exit fullscreen mode

Now the component loads only on client → no mismatch.

4.Make sure data is consistent between server and client:- Use server-only fetching (app router) or React Query with proper hydration.

Hydration errors happen when the HTML React expects in the browser doesn’t match the HTML generated by Next.js on the server.



Source link