0Pricing
React Academy · レッスン

Hydrationエラー:原因と修正

serverとclientのHTMLの不一致を特定し、suppressHydrationWarningで修正します。

「Hydrationエラー:原因と修正」はCoddyKit上の無料React Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

ハイドレーションエラーとは

ハイドレーションエラーは、ReactがサーバーでレンダリングしたHTMLと、クライアント上でReactが期待する仮想DOMが一致しない場合に発生します。Reactは警告をログに出力し、コンポーネントを最初から再レンダリングするため、画面が一瞬ちらつきます。

よくある原因1:ランダムな値

レンダリング中にMath.random()、Date.now()、crypto.randomUUID()を使うと、サーバーとクライアントで異なる値が生成されます。

// Bad — different on server vs client:
<div id={Math.random().toString()}>...</div>

// Fix — use useId() (stable across server/client):
import { useId } from 'react';
function Component() {
  const id = useId();
  return <div id={id}>...</div>;
}

よくある原因2:ブラウザー専用API

レンダリング中にlocalStorage、window.innerWidth、navigatorを読み取ると、サーバー上でクラッシュしたり、異なる値が生成されたりします。

// Bad — localStorage doesn't exist on server:
<div>{localStorage.getItem('theme')}</div>

// Fix — read in useEffect (client-only):
const [theme, setTheme] = useState('light');
useEffect(() => {
  setTheme(localStorage.getItem('theme') ?? 'light');
}, []);

よくある原因3:日付と時刻のフォーマット

ロケールに対応した日付のフォーマットでは、サーバー(UTCまたはNodeのロケール)とクライアント(ブラウザーのロケール)で異なる文字列が返されます。

// Risky — locale may differ:
<time>{new Date().toLocaleDateString()}</time>

// Fix — use a consistent locale:
<time>{new Date().toLocaleDateString('en-US', { timeZone: 'UTC' })}</time>

よくある原因4:不正なHTMLの入れ子

Reactは仮想DOMからクライアント側のHTMLを生成しますが、不正なHTMLの入れ子(例:<p>の中に<p>を入れること)があると、ブラウザーによるDOMの再構成が異なるため、不一致が発生します。

// Bad — browser auto-closes the nested <p>:
<p>Outer <p>Inner</p> text</p>

// Fix — use <div> or correct semantic elements:
<div>Outer <p>Inner</p> text</div>

よくある原因5:状態に基づく条件付きレンダリング

ユーザー認証や画面幅など、クライアント側でのみ取得できる状態に応じて異なる表示をするコンポーネントでは、サーバーがその状態なしでレンダリングするため、不一致が発生します。

// Bad — server renders 'Guest', client re-renders 'Alice' immediately:
<h1>{user?.name ?? 'Guest'}</h1>

// Fix — use a mounted guard to defer client-only rendering:
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return <h1>Guest</h1>; // match server output

suppressHydrationWarning

クライアント側でフォーマットするタイムスタンプなど、意図的に不一致が発生する要素にはsuppressHydrationWarningを使います。この要素に対する警告だけを抑制します。

<time suppressHydrationWarning dateTime={isoDate}>
  {new Date(isoDate).toLocaleString()}
</time>

ssr: falseを指定した動的インポート

Next.jsでは、dynamic(fn, { ssr: false })を使うと、コンポーネントがサーバー上でレンダリングされるのを完全に防げます。これにより、クライアント専用コンポーネントのハイドレーションの不一致を解消できます。

import dynamic from 'next/dynamic';

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

export default function Dashboard() {
  return <ClientOnlyChart />; // only renders in the browser
}

ハイドレーションエラーのデバッグ

React 18は開発中、DOMノードの不一致箇所を示す詳細なハイドレーションエラーメッセージをログに出力します。ブラウザーのDevToolsを使って、サーバーのHTMLとReactツリーを調べます。

安定したIDのためのuseId

useId()は、サーバーとクライアントのレンダリングで一貫した、安定した一意のIDを生成します。idとhtmlForの組み合わせやARIA属性に使います。

function FormInput({ label }: { label: string }) {
  const id = useId();
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input id={id} />
    </div>
  );
}

ハイドレーションエラーのテスト

Next.jsアプリを開発モード(npm run dev)で実行し、ブラウザーのコンソールを確認します。ハイドレーションの不一致は、コンポーネントのスタックトレースを含む赤い警告として表示されます。

理解度チェック

localStorageの読み取りによってサーバーとクライアントで異なる表示をするコンポーネントには、どのような修正が最適ですか。

まとめ

ハイドレーションの不一致は、ランダムな値、ブラウザー専用API、ロケール依存のフォーマット、不正なHTMLの入れ子、クライアント専用の条件付きレンダリングによって発生します。useId()、クライアント専用の状態に対するuseEffect、意図的な差異に対するsuppressHydrationWarning、クライアント専用コンポーネントに対するdynamic({ ssr: false })で修正します。

よくある質問

「Hydrationエラー:原因と修正」レッスンは無料ですか?

はい。「Hydrationエラー:原因と修正」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「Hydrationエラー:原因と修正」で何を学びますか?

serverとclientのHTMLの不一致を特定し、suppressHydrationWarningで修正します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「Hydrationエラー:原因と修正」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. React SSRの内部動作
  2. Hydrationエラー:原因と修正
  3. 選択的HydrationとHTMLストリーミング
  4. Islands Architectureパターン
← React Academyに戻る