Next.jsでTableタグを使ったら謎のエラーに苦しめられた【解消方法と原因考察】
前置き
入社3ヶ月目の駆け出しフロントエンドエンジニアによる備忘録です。
今回はNext.jsでTableタグを使用した際によく陥るエラーの解消方法と原因考察の記事となります。
解決策だけ知りたい人は さっそくやってみよう から読んで下さい。
◎ 今回やりたいこと
まず Next.js にて Table
タグを、
・・・ // importとかいろいろ
export default function ExampleTable() {
const exampleInfos = [・・・]; // tableタグに入力したいデータ
return (
<table>
{exampleInfos.map((exampleInfo, index) => ( // trタグをデータの数だけ追加
<tr key={index}>
<th>{exampleInfo.tableHeading}</th>
<td>{exampleInfo.tableData}</td>
</tr>
))}
</table>
);
}
のように記述し、npm run dev
したところ、
http://localhost:3000/ で下記のようなエラーが表示されました。
最初はエラー文に従って解決方法を模索したのですが、残念ながら全く状況が改善されませんでした。
最終的に思わぬ形でエラーを解消できましたので、今回はその方法を共有していきたいと思います。同じ苦しみを味わう仲間が一人でも減ることを祈ります。
◎ さっそくやってみよう
エラー解消の方法は実に簡単です。
tr
を、thead
または tbody
tfoot
のいずれかで囲めばよいだけです。
つまり、table
の直下に、丸裸の状態でtr
を置くのを辞めるだけで今回のエラーをまとめて解消できます。
今回はtbody
タグで囲った例を以下に示します。
↓↓
・・・ // importとかいろいろ
export default function ExampleTable() {
const exampleInfos = [・・・]; // tableタグに入力したいデータ
return (
<table>
+ <tbody>
{exampleInfos.map((exampleInfo, index) => ( // trタグをデータの数だけ追加
<tr key={index}>
<th>{exampleInfo.tableHeading}</th>
<td>{exampleInfo.tableData}</td>
</tr>
))}
+ </tbody>
</table>
);
}
これで無事エラーは解消されました。
◎ エラーの原因を考察する
まずはじめに「HTMLの入れ子のルールを破ってしまったのでは?」と疑ってみましたが、MDNで確認したところ、table
タグの直下にtr
タグを入れ子にすることを禁止しているようには見受けられませんでした。
ということは Next.js または React によるエラーであると考えられます。
どうやら ReactDOM.hydrateRoot はサーバサイドで生成された DOM 構造と、クライアントサイドで生成された 仮想DOM が一致していることを期待しており、仮想DOM では table > tr
というデータ構造を想定していなかったため今回のようなエラーが発生してしまったようです。
つまり、MDNでは問題ないとされているHTML構造であっても、仮想DOMが想定しているHTML構造と一致しなかった場合は今回と同様のエラーが容赦なく飛んでくるという認識でいた方がよさそうですね。
うーんややこしい。
ちなみに私はこのエラーを自力での解決するのに軽く1時間半くらいは持っていかれました…
今回の記事が誰か1人でも悩める人を救うキッカケとなれば嬉しく思います。
Discussion