Next.jsはサーバーコンポーネントとクライアントコンポーネントの両方をサポートしています。
サーバーサイドレンダリング: コンポーネントがサーバー上でレンダリングされる際、document
や window
などのブラウザ専用オブジェクトは存在しません
ハイドレーション: サーバーでレンダリングされたHTMLがクライアントに送られた後、Reactがブラウザ上でコードを「ハイドレート」(活性化)する過程で、このエラーが発生しています
import { useEffect, useState } from 'react';
function MyComponent() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
// ここで安全に document にアクセスできる
}, []);
if (!mounted) {
return null; // または初期表示用の代替表示
}
// document を使用するコード
return <div>...</div>;
}
import dynamic from 'next/dynamic';
const ClientSideComponent = dynamic(
() => import('../components/ClientComponent'),
{ ssr: false } // サーバーサイドレンダリングを無効化
);
function Page() {
return <ClientSideComponent />;
}
function MyComponent() {
const isBrowser = typeof window !== 'undefined';
// document を使用するコードを条件付きで実行
return (
<div>
{isBrowser && /* document を使用するコード */}
</div>
);
}
'use client'
を追加すると、そのコンポーネントとその子コンポーネントはクライアントサイドでのみ実行されます。'use client'
import { useEffect } from 'react';
export default function ClientComponent() {
useEffect(() => {
// ここで安全に document にアクセスできる
const element = document.getElementById('some-id');
// ...
}, []);
return <div>...</div>;
}
Next.jsではクライアントサイドの処理とサーバーサイドの処理を適切に分けることが重要です。document
オブジェクトを使用する必要がある場合は、上記のいずれかの方法を使用して、そのコードがクライアントサイドでのみ実行されるようにしましょう。
https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading
import { MyComp } from "../components/MyComp";
↓
import dynamic from "next/dynamic";
const MyCompNoSSR = dynamic(() => import("./MyComp"), { ssr: false });
以上で、SSRが回避されます。
import MyComp from "../components/MyComp";
↓
import dynamic from "next/dynamic";
const MyCompNoSSR = dynamic(
() => import("./MyComp").then((modules) => modules.MyComp),
{ ssr: false },
);
以上です。
このように 呼び出されるコンポーネント側に記述することもできます
import App from '../components/App'
export default function About() {
return (
<App>
<p>About Page</p>
</App>
)
}
↓
import dynamic from 'next/dynamic'
import App from '../components/App'
const About = ()=> {
return (
<App>
<p>About Page</p>
</App>
)
}
export default dynamic(() => Promise.resolve(About), {
ssr: false
})
以上で、SSRが回避されます。
ページをリロードしてhtmlソースを見てみます。
<p>About Page</p>
がなければ、SSRされていません。
React18以上が必要です。必ずバージョンを確認しましょう
const DynamicLazyComponent = dynamic(() => import('../components/hello4'), {
suspense: true,
})
https://nextjs.org/docs/advanced-features/dynamic-import