本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

Hydration failed の直し方

実際に出るエラー

Hydration failed because the server rendered text didn't match the client.
As a result this tree will be regenerated on the client.

This can happen if a SSR-ed Client Component used:
- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

サーバーで描いた HTML と、ブラウザが最初に描いた内容が食い違ったときに出るエラーです。

何が起きているか

どこで食い違いが起きるか
  1. Server
    サーバーが HTML を作る

    たとえば new Date() の値が 10:00 だったとする。

  2. Browser
    その HTML が表示される

    この時点では 10:00 と出ている。

  3. Browser
    React が描き直して突き合わせる

    ブラウザでは 10:05。食い違うのでこのエラーになる。

Client Component は、最初の1回だけサーバーでも実行されます。その結果が HTML として送られ、ブラウザ側で React が同じものをもう一度描いて、両者を突き合わせます。この突き合わせが hydration です。

このとき中身が食い違うと、React は「サーバーが送ってきた HTML は信用できない」と判断し、その部分を作り直します。そのときに出るのがこのエラーです。

同じコードなのに結果が変わる。React はこの差を見つけて作り直す
サーバーが作った HTML
<p>2026-08-28T01:40:31.478Z</p>

描いた瞬間の時刻。HTML に焼き込まれて配られる。

ブラウザが描き直した結果
<p>2026-08-28T01:40:31.676Z</p>

表示した瞬間の時刻。198ミリ秒ずれている。ここが食い違いになる。

致命的ではない、が放置してはいけない

Next.js の開発オーバーレイでは Recoverable Error(回復可能)と表示されます。実際、React はその部分を作り直すのでページは動きます。

ただし、

  • 作り直しのぶん、表示が一瞬ちらつく
  • サーバーが作った HTML が捨てられるので、最初の表示が速いという利点が消える
  • 食い違いの原因が「ブラウザ限定の値を描画時に読んでいる」なら、別の不具合の予兆でもある

ので、直すべきです。

原因はほぼこの5つ

サーバーとブラウザで結果が変わるもの
書いたものサーバーブラウザ
new Date() / 現在時刻描いた時刻表示した時刻
Math.random()その時の値別の値
window / localStorageそもそも無い実際の値
typeof window での分岐false 側true 側
ブラウザ拡張による書き換え起きない起きることがある

React 自身がエラー文の中で候補を挙げてくれます。実際に多いのは上の3つです。

1. typeof window で分岐している

'use client'
 
export function Stored() {
  const v = typeof window === 'undefined' ? 'server' : 'browser'
  return <p>{v}</p>   // サーバーとブラウザで必ず違う
}

window is not defined を消すためにこう書くと、エラーが hydration の不一致に置き換わるだけです。

2. 時刻や乱数を描画に使っている

return <p>{new Date().toISOString()}</p>   // 呼ぶたびに変わる
return <p>{Math.random()}</p>

サーバーで描いた瞬間と、ブラウザで描いた瞬間は必ずずれます。

3. 日付や数値の書式が環境で変わる

toLocaleString() は、サーバーとブラウザでロケールやタイムゾーンが違うと別の文字列になります。

4. HTML の入れ子が正しくない

<p> の中に <div> を入れるなど。ブラウザが勝手に構造を直すので、React が描いたものと合わなくなります。

5. ブラウザ拡張が HTML を書き換えている

自分のコードに問題が無いのにこのエラーが出る場合、これを疑います。シークレットウィンドウで開くと再現しないなら、拡張が原因です。

最短の確認手順

開発モードで開いてください。オーバーレイが食い違った箇所を差分で見せてくれます。

+ 2026-08-28T01:40:31.676Z    ← Client(ブラウザが描いたもの)
- 2026-08-28T01:40:31.478Z    ← Server(HTML として届いたもの)
 
components/Clock.tsx (5:10) @ Clock

行番号まで出るので、原因の特定はここでほぼ終わります。

本番ビルドでは Minified React error #418 としか出ません。必ず開発モードで再現させてください。

直し方

推奨:最初の描画では出さず、useEffect の後に出す

'use client'
 
import { useEffect, useState } from 'react'
 
export function Clock() {
  const [now, setNow] = useState<string | null>(null)
 
  useEffect(() => {
    setNow(new Date().toISOString())
  }, [])
 
  return <p>{now ?? '—'}</p>
}

サーバーもブラウザも最初は null を描くので、食い違いません。値が入るのは hydration の後です。

値をサーバーから渡す

時刻を「ページを作った時刻」として見せたいなら、Server Component で決めて props で渡します。両方が同じ値を描くので一致します。

// Server Component
const now = new Date().toISOString()
return <Clock now={now} />

書式をサーバーと揃える

toLocaleString() を使うなら、ロケールとタイムゾーンを明示します。

new Intl.DateTimeFormat('ja-JP', { timeZone: 'Asia/Tokyo' }).format(d)

どうしても違ってよい場合

1要素だけなら suppressHydrationWarning で警告を止められます。ただし警告を消すだけで、作り直しは起きます。乱用しないでください。

やってはいけない直し方

const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return null

「マウントするまで何も描かない」という形です。エラーは消えますが、

  • そのコンポーネントの初期表示が丸ごと無くなる
  • サーバーで HTML を作った意味が消える
  • 表示が遅れて見える

ので、部分的な回避にしか使えません。食い違う値だけを後から入れるほうが素直です。

なぜ開発中に気づきにくいのか

気づけます。むしろ開発モードのほうが親切です。問題は逆で、本番でしか出ないケースがあることです。

  • 利用者のタイムゾーンやロケールが開発環境と違う
  • 利用者のブラウザ拡張が HTML を書き換える
  • 本番でだけ通るデータの経路がある

本番で #418 を見たら、まず同じ条件を開発モードで再現させてください。

再発防止

  • 描画の中で「呼ぶたびに変わる値」を使わない
  • typeof window で表示を分岐させない
  • ロケールに依存する書式は、必ずロケールとタイムゾーンを明示する

関連するエラー

window をサーバー側で参照した場合は、hydration の前に落ちます。

ReferenceError: window is not defined

typeof window での分岐は、このエラーを hydration の不一致に置き換えているだけ、という関係になります。

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

use client が付いています。ブラウザで開くと何が起きますか。

この問題を解くこのテーマの問題 3 問