はじめに
ChakraUIのコンポーネントとHTMLタグの関係性を理解していなかったため、hydrationエラーが発生しました。この記事では、そのエラーの原因と解決方法について解説します。
エラーメッセージ
In HTML, <div> cannot be a descendant of <p>.
This will cause a hydration error.
エラーが発生したコード
<Box>
<Heading fontSize={16} fontWeight="bold" textAlign="left">
自己紹介
</Heading>
<Text fontSize={14} color="gray.600" textAlign="left" mb={4}>
<div dangerouslySetInnerHTML={{ __html: user?.description ?? "" }} />
</Text>
</Box>
原因
エラーの根本原因は、HTMLの入れ子ルール違反でした。Chakra UIの<Text>コンポーネントは、内部的にHTMLの<p>タグとしてレンダリングされます。一方、dangerouslySetInnerHTMLで挿入されるHTMLコンテンツに<div>タグが含まれていたため、「<p>タグの中に<div>タグがある」という無効な構造が生成されました。
HTMLの仕様では、<p>要素内にブロック要素(<div>など)を含めることは許可されていません。そのため、ブラウザがDOMを正しく構築できず、hydrationエラーが発生しました。
実際の構造は以下のようになっていました。
<Text>
<div dangerouslySetInnerHTML={{ __html: "..." }} />
</Text>
生成されたHTMLは以下のような状態でした。
<p> ← Textコンポーネント
<div> ← dangerouslySetInnerHTML
<p>...</p>
</div>
</p>
解決方法
<p>タグとしてレンダリングされる<Text>コンポーネントの代わりに、<div>タグとしてレンダリングされる<Box>コンポーネントに変更することで問題を解決することができました。
<Box>
<Heading fontSize={16} fontWeight="bold" textAlign="left">
自己紹介
</Heading>
<Box fontSize={14} color="gray.600" textAlign="left" mb={4}>
<div dangerouslySetInnerHTML={{ __html: user?.description ?? "" }} />
</Box>
</Box>
ChakraUIのコンポーネントとHTMLタグの関係性
ChakraUIのコンポーネントとHTMLのタグの対応表は以下のようになっています。
まだまだたくさんのコンポーネントがありますが、主要なものだけまずは調査してみました。
ChakraUIコンポーネント | HTMLタグ | 特徴 |
---|---|---|
<Text> | <p>タグ | テキスト・段落要素 |
<Box> | <div> タグ | 汎用コンテナ |
<Flex> | <div> タグ | display: flex がデフォルト |
<Stack> | <div> タグ | 子要素を縦または横に並べる(デフォルトは縦) |
<HStack> | <div> タグ | 水平方向のスタック |
<VStack> | <div> タグ | 垂直方向のスタック+中央寄せ |
<Grid> | <div> タグ | display: grid がデフォルト |
<Container> | <div> タグ | 幅制限+中央寄せコンテナ |
<Heading> | <h1>, <h2>, <h3>など | sizeプロパティで決定 |
<Button> | <button>タグ | フォーム送信・アクション |
<Input> | <input>タグ | テキスト入力 |
<Textarea> | <textarea>タグ | 複数行テキスト入力 |
<Select> | <select>タグ | ドロップダウン選択 |
<Checkbox> | <input type="checkbox"> | チェックボックス |
<Radio> | <input type="radio"> | ラジオボタン |
<Image> | <img>タグ | 画像表示 |
<Link> | <a>タグ | リンク |
おわりに
今回は、Chakra UIコンポーネントが内部的にどのHTMLタグに対応しているかを理解することの重要性を改めて実感する良い機会となりました。同様のエラーに遭遇した方の助けになれば幸いです。
参考