React/Next.js 学習を進めていると Server Component と Client Component をケースに応じて使い分けることかと思います。
そんな時に下記のようなエラーに出会った経験がある方も多いのではないかと思います。
Error: Hydration failed because the initial UI does not match
what was rendered on the server.
この記事が「ハイドレーションが何かピンとこない人」や「誰かに説明したい人」の手助けになれば幸いです。
先に結論
- Hydration = サーバーで作った HTML に、ブラウザで JS を後付けして「操作できる状態」にする工程
- イメージは インスタント味噌汁にお湯を注ぐ作業
- Server Component は最初から「お湯不要」なので、Hydration のコストが発生しない=速い
Hydration の語源
英語の hydrate = 「水を与える」。
つまり、乾いた HTML に JS という水を注いで動かす、というイメージ。
よく見る説明ですが、個人的にはあまりピンときませんでした…。
インスタント味噌汁で例えると
インスタント味噌汁を思い浮かべてみてください。
[乾燥状態] [水を注ぐ] [完成]
中身は揃ってる → お湯をかける → 飲める味噌汁
(HTML だけ) (JS 実行) (操作可能)
| 段階 | 味噌汁 | Web ページ |
|---|---|---|
| ① 中身 | 乾燥した具材 | サーバーで作った HTML |
| ② お湯 | お湯を注ぐ | JS バンドルが届く |
| ③ 反応 | 具材がほぐれる | イベントハンドラが要素に紐づく |
| ④ 完成 | 飲める | 操作できる |
具材だけ見せられても食べられへんし、HTML だけあってもボタンは押せへん。
お湯(= JS)が要るわけです。
ブラウザでの実際の流れ
① サーバーで HTML 生成
<button>クリック</button> ← 見た目はある
↓
② ブラウザに HTML 届く
表示される(速い!)
でも... ボタン押しても何も起きない
↓
③ JS バンドルがダウンロード
↓
④ Hydration 開始
- React が HTML を「自分のもの」として認識
- イベントハンドラ(onClick)を要素に紐付け
↓
⑤ 完成
ボタン押すと反応する
ここで重要なのは、②と④の間に「見えてるけど操作できない時間」があること。
これが Web Vitals でいう TTI(Time To Interactive) の遅れにつながります。
Server Component が「速い」理由
ここまで理解すると、Server Component の利点が見えてきます。
Client Component の場合
HTML 表示 → JS ダウンロード → Hydration → 操作可能
(Hydration のコストが乗る)
Server Component の場合
HTML 表示 → そのまま完成!
(Hydration 不要、JS そのものがブラウザに来ない)
ポイントは:
- Server Component
→ ブラウザで実行されない
→ Hydration されない - Client Component
→ ブラウザで実行される
→ Hydration される
これが「Server Component は速い」と言われる構造です。
Hydration Mismatch エラー
開発中に発生するエラーとして下記のようなエラーがあります。
Error: Hydration failed because the initial UI does not match
what was rendered on the server.
これは、
- サーバーで生成した HTML
- ブラウザで JS が組み立てた結果
が一致しないことで発生します。
よくあるエラー原因
| 原因 | 例 |
|---|---|
| サーバーとブラウザで値が変わる関数 |
Date.now(), Math.random()
|
| ブラウザ専用 API の分岐 | typeof window !== "undefined" |
| ユーザーロケールに依存する処理 | 日付フォーマット、通貨表示 |
対処の基本
-
固定値を使う(ダミーデータでは
new Date("2026-04-01")のような固定値) - クライアント側の処理は
useEffect内で -
どうしても必要なら
suppressHydrationWarning(最終手段)
一言で覚える
「サーバーで作った HTML を、ブラウザで React が引き取る儀式」 = Hydration
味噌汁の比喩でいうと
「具材を作る人(サーバー)と、お湯を注ぐ人(ブラウザ)が違う」
まとめ
- Hydration は HTML に JS を後付けする工程
- Server Component は最初から「動かす必要のない静的なもの」として届くので Hydration 不要
- Hydration Mismatch エラーは「サーバーとブラウザで結果が変わる処理」が原因
Hydration が何か理解できると Server Component と Client Component の使い分けの基準が1つできたと思います。
「ブラウザで動かす必要があるか?」が判断基準とするのが良いでしょう。
これから実装する際は、
- ブラウザで動かさないなら Server Component
- ブラウザで動かすなら Client Component で
"use client"を付ける
を意識して実装してみてください。
用語整理
| 用語 | 意味 |
|---|---|
| SSR (Server-Side Rendering) | サーバーで HTML を生成すること |
| CSR (Client-Side Rendering) | ブラウザで HTML を組み立てること |
| Hydration | SSR で作った HTML に JS を後付けする工程 |
| TTI (Time To Interactive) | 操作可能になるまでの時間 |
| Server Component | サーバーでのみ実行され、JS バンドルに含まれない(Hydration 不要) |
| Client Component | ブラウザでも実行され、Hydration が必要 |