MeWrite Docs

Hydration failed because the initial UI does not match

Next.jsでサーバーとクライアントのHTMLが一致しない場合に発生

概要

Hydration failedは、Next.jsでサーバーサイドレンダリング(SSR)されたHTMLと、クライアントサイドで生成されるHTMLが一致しない場合に発生するエラーです。

エラーメッセージ

Error: Hydration failed because the initial UI does not match what was rendered on the server.
Warning: Text content did not match. Server: "Hello" Client: "World"

原因

  1. Date/時刻の不一致: サーバーとクライアントで異なる時刻
  2. ブラウザ固有API: window, localStorageをSSR中に使用
  3. 条件付きレンダリング: サーバーとクライアントで異なる条件
  4. HTML構造の誤り: pタグ内にdivなど

解決策

1. useEffectでクライアントのみの処理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { useState, useEffect } from 'react';

function Component() {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) return null;

  return <div>{window.innerWidth}</div>;
}

2. dynamic importでSSRを無効化

1
2
3
4
5
6
import dynamic from 'next/dynamic';

const ClientOnlyComponent = dynamic(
  () => import('./ClientOnlyComponent'),
  { ssr: false }
);

3. 時刻表示を統一

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 悪い例
<p>{new Date().toLocaleString()}</p>

// 良い例
const [time, setTime] = useState('');

useEffect(() => {
  setTime(new Date().toLocaleString());
}, []);

<p>{time}</p>

4. suppressHydrationWarning

1
2
3
4
// 意図的な不一致の場合のみ使用
<time suppressHydrationWarning>
  {new Date().toLocaleString()}
</time>

5. HTML構造を修正

1
2
3
4
5
6
7
8
9
// 悪い例:pタグ内にdiv
<p>
  <div>Invalid nesting</div>
</p>

// 良い例
<div>
  <p>Valid nesting</p>
</div>

6. localStorageの安全な使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(initialValue);

  useEffect(() => {
    const stored = localStorage.getItem(key);
    if (stored) setValue(JSON.parse(stored));
  }, [key]);

  return [value, setValue];
}

JavaScript の他のエラー

最終更新: 2025-12-09