Next.js で「ReferenceError: window is not defined」が解消できない
サーバー側(SSR・ビルド時のプリレンダ)で `window` や `document` を参照しているのが原因。
ブラウザ専用コードは `useEffect` 内へ移すか、`next/dynamic` の `ssr: false` で読み込む。
#nextjs#ssr#window#app-router#client-component
公開: 更新:
要約
ReferenceError: window is not defined は、サーバー側で実行されるコードがブラウザ専用のオブジェクトに触れたときに出ます。
Next.js はページをサーバーやビルド時にいったん描画(プリレンダ)します。
その時点に window は存在しません。
直し方は「ブラウザでだけ動かす」ことの徹底です。
よくある原因
- Server Component やモジュールのトップレベルで
window/document/localStorageを読んでいる。 - ブラウザ前提のライブラリを通常 import し、ビルド時に評価されている。
useEffectの外、つまりレンダー本体でブラウザ API を呼んでいる。
解決策
1. useEffect の中へ移す
useEffect はクライアントでのみ実行されるため、ブラウザ API はここに置きます。
'use client';
import { useEffect, useState } from 'react';
export function Width() {
const [w, setW] = useState(0);
useEffect(() => {
setW(window.innerWidth); // クライアントでのみ実行
}, []);
return <span>{w}</span>;
}2. ssr:false で動的 import する
コンポーネントごとプリレンダから外したいときは、Client Component から next/dynamic を使います。
'use client';
import dynamic from 'next/dynamic';
const Chart = dynamic(() => import('./Chart'), { ssr: false });3. typeof でガードする
単発の参照なら、アクセス前に存在チェックを入れます。
if (typeof window !== 'undefined') {
// ここはブラウザでのみ動く
}