Hydration failedの解決について
備忘録で残すシリーズ
そもそも原因
Hydration エラーは「SSR で出力された HTML と CSR での HTML が違う場合」に発生する
→サーバー側とクライアント側で描画される情報に不一致が生じるのでエラーになる
エラーが起きたコード
クライアントが利用しているブラウザによって変化させたい項目があった。
import { useEffect, useState } from "react";
export default function Home() {
const [preLink, setPreLink] = useState("");
useEffect(() => {
// ユーザーエージェントでブラウザ判定
const userAgent = navigator.userAgent;
if (userAgent.includes("Chrome") && !userAgent.includes("Edg")) {
// Chrome なら Edge で開くスキームを使用
setPreLink(microsoft-edge:);
} else {
// Edge またはその他のブラウザでは通常の URL
setPreLink("");
}
}, []);
return (preLink)
}
発生したエラー
Hydration failed because the server rendered HTML 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
エラー解消コード
解決方法
useStateの初期状態をnullに
import { useEffect, useState } from "react";
export default function Home() {
//ここを更新、初期状態を null に
const [preLink, setPreLink] = useState<string | null>(null);
//SSR ではuseEffectが無視される
useEffect(() => {
// ユーザーエージェントでブラウザ判定
const userAgent = navigator.userAgent;
if (userAgent.includes("Chrome") && !userAgent.includes("Edg")) {
// Chrome なら Edge で開くスキームを使用
setPreLink(microsoft-edge:);
} else {
// Edge またはその他のブラウザでは通常の URL
setPreLink("");
}
}, []);
return preLink;
}
原因と解決方法(ざっくり)
原因
Hydration エラーは「SSR で出力された HTML と CSR での HTML が違う場合」に発生する
→サーバー側とクライアント側で描画される情報に不一致が生じるのでエラーになる
なぜ解決できるか
SSR では null を返して何も描画しないという特徴を活かす。
SSRではnull、CSRで任意の文字列となった場合、対象の要素は新規の要素として判定されるためこれらは矛盾と判定されない。
SSR で null だった場合、そもそも HTML がないので、存在しない要素となる。
これにより、setStateで更新された要素は、「クライアント側で新しく追加された要素」として処理される。
→Next.js の Hydration(SSR と CSR の照合) で競合しない
つまり
SSRではnull、CSRで任意の要素となった場合、新規の要素として判定されるためこれらは矛盾と判定されない。
今回の解決方法
SSR では null を返し、SSR時点で HTML を生成しないことで、Hydration エラーを防ぐ。