1. Omid Sayfun
  2. /
  3. Notebook
  • Home
  • About
  • Notebook
  • Token Usage
  • Whisper Usage
Tools
  • Agent Knowledge Base

Next.js Hydration Window Issue

May 29, 2024 · Updated on August 09, 2026

Coming from a React environment, I wrote a page view tracker like this:

"use client";
import React from 'react';
 
export const TrackPageView = () => {
	React.useEffect(() => {
		trackView({
			url: window.location.href,
			referrer: document.referrer,
		});
	}, [window.location.href, document.referrer]);
 
	return <></>;
}

But this doesn’t work in Next.js. If you test it out, you would either get:

ReferenceError: window is not defined

which is clear enough, or you might encounter:

TypeError: Response body object should not be disturbed or locked

This happens because you’re calling the trackView server action and the signal is aborted. The TypeError: Response body object should not be disturbed or locked message comes from that aborted request, not from your tracking code. Both errors trace back to Next.js hydration. Even though the component is marked as a client component, hydration also renders it during the server pre-render.

I write short, practical notes like this one. Get the next one by email:

Unsubscribe anytime.

Next.js hydration makes server-rendered HTML interactive

Hydration in Next.js is the process that makes server-rendered HTML interactive on the client side. Next.js produces static HTML during the server-side rendering (SSR) phase. Once the JavaScript loads and runs in the browser, React attaches to that HTML and the page becomes a fully interactive app.

Hydration buys you SEO, first-load speed, and interactivity

Hydration offers several advantages:

  1. SEO and Performance: By rendering the initial HTML on the server, Next.js ensures that search engines can index the content, improving SEO. Additionally, the initial load time is faster because the user receives a fully-rendered page almost immediately.
  2. Interactivity: Once the static HTML is hydrated, the page becomes interactive, allowing for a dynamic user experience with all the benefits of React.
  3. Consistency: Hydration ensures that the server-rendered HTML and the client-side React components are synchronized, providing a stable user experience.

Hydration errors start where your code assumes a browser

While hydration is beneficial, it comes with its own set of challenges:

  1. Window is Not Defined: During server rendering there is no window object, so ReferenceError: window is not defined is thrown as soon as your code reads it. window is a browser-specific global object, and it does not exist in the Node.js environment where the server-side code runs.
  2. Hydration Mismatches: If the server-rendered HTML does not match the HTML generated by React on the client, hydration can fail, causing UI glitches or errors.
  3. Performance Overhead: Hydration can add a performance overhead because the browser needs to parse and execute the JavaScript code to make the page interactive.

Read the path from usePathname instead of window

Swap window.location.href for the usePathname hook from next/navigation, and drop document.referrer from the dependency array:

"use client";
import React from "react";
import { usePathname } from "next/navigation";
 
export const TrackPageView = () => {
	const pathname = usePathname();
 
	React.useEffect(() => {
		trackView({
			url: pathname,
			referrer: document.referrer,
		});
	}, [pathname]);
 
	return <></>;
};

Removing document.referrer from the dependency array matters as much as the hook swap. Everything inside useEffect runs on the client only. The dependency array does not get that guarantee, so during hydration you can still get an error saying document is not defined. With pathname as the only dependency, the effect runs once per navigation and never reads a browser global on the server.

suppressHydrationWarning does not help here. It silences a hydration mismatch warning on a single element, and it does not give the server a window object.

Food for thought

Hydration is a powerful feature of Next.js that bridges the gap between server-rendered and client-rendered applications. While it brings many benefits, it also requires careful handling of client-side code.

In summary, when working with Next.js:

  1. Be cautious with direct window and document usage.
  2. Understand the hydration process and its implications.
  3. Use Next.js hooks and utilities to manage client-side interactions effectively.

Join My Newsletter

Occasional notes on software, tools, and things I learn. No spam.

Unsubscribe anytime.

Continue Reading

  • Embeddings rot too. Running pgvector in production.Aug 28, 2026
  • Stop shipping retrieval changes on vibesAug 25, 2026
  • Your RAG is confidently wrong without hybrid searchAug 21, 2026
  • Stop tuning everything. pgvector has three knobs that matter.Aug 18, 2026
  • Your agent's knowledge base is lying to you. Run these 14 checks.Aug 18, 2026