IT-Q

「Hydration failed」というエラーが出ました。何が起きていますか。

サーバーが生成したHTMLと、ブラウザで React が最初に描画した結果が食い違っています。ランダム値や現在時刻、localStorage の参照など、両者で違う値になるものが原因です。

面接官が見ているのはハイドレーションを仕組みとして説明できるか。

これは「'use client' のコンポーネント本体に window を直接書いても、サーバーでは実行されないので安全ですか。」への追撃質問です。

よくある答えと、面談でどう見られるか

  • サーバーが返した HTML と、ブラウザでの初回描画が食い違っている
    その通りです。原因は日時・乱数・ブラウザ専用APIの参照・不正なHTML入れ子あたりに集中します。
  • JavaScript の読み込みに失敗している
    読み込み失敗なら「操作できない」ですが、この警告は出ません。ハイドレーションは「HTML と再描画結果が一致する前提」が崩れたときに出ます。
  • Client Component にすべきものが Server Component のままになっている
    それは別のエラー(フックが使えない等)で出ます。むしろ 'use client' を足しても、この警告は直りません。Client Component もプリレンダーされるためです。
  • サーバーとクライアントで異なるバージョンの React が動いている
    理屈としてはあり得ますが、通常の Next.js プロジェクトではまず起きません。先に疑うべきは自分のコードの方で、日時や localStorage の参照が定番です。

面接官は何を見ているか

  • サーバーで作ったHTMLとクライアントの初回描画が食い違っていると言えた
  • 原因の候補を具体的に挙げられた
  • 「とりあえず 'use client' を付ける」では直らないと理解している

模範解答

サーバーが生成した HTML と、ブラウザで React が最初に描画した結果が食い違っています。

ハイドレーションは、サーバーが返した静的な HTML にイベントハンドラを結び付けて操作可能にする処理です。前提として「同じものが描画されるはず」なので、ズレると React が警告を出します。

原因はだいたい決まっていて、(1) Date や Math.random のように実行のたびに値が変わるもの、(2) typeof window === 'undefined' でサーバーとクライアントの分岐を書いている、(3) localStorage の値を初期 state に入れている、(4) HTML として不正な入れ子(p の中に div、a の中に a など)でブラウザが構造を補正した、あたりです。

注意点として、'use client' を付けても直りません。Client Component もサーバーでプリレンダーされるので、ズレる条件は変わらないからです。

もう1つ、時間を溶かしやすい原因を挙げておくと、ブラウザ拡張が HTML を書き換えているケースがあります。公式も原因の一覧に載せています。自分のコードをいくら見ても見つからないときは、シークレットウィンドウや拡張を切った状態で再現するかを先に確かめます。同じ理由で、CDN 側の HTML 自動圧縮が原因になることもあります。

ここからどう深掘りされるか

この問いに答えられた場合、面談は次の質問に進みます。