できない.dev

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 は存在しません。

直し方は「ブラウザでだけ動かす」ことの徹底です。

よくある原因

  1. Server Component やモジュールのトップレベルで window / document / localStorage を読んでいる。
  2. ブラウザ前提のライブラリを通常 import し、ビルド時に評価されている。
  3. 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') {
  // ここはブラウザでのみ動く
}

この記事は役立ちましたか?