key

前回の警告を消します

map でカードを並べたとき、コンソールに次のような警告が出ていました。

Warning: Each child in a list should have a unique "key" prop.

直し方は簡単で、map が返す一番外側の要素に key を付けるだけです。

{works.map((work) => ( <div className="work-card" key={work.id}> <h2>{work.title}</h2> </div> ))}

大事なのは、なぜ React がこれを求めるのかのほうです。

key は「どの行がどのデータか」の印

React は state が変わるたびに、前の画面と新しい画面を見比べて、違うところだけを書きかえます。このとき一覧の中身が並べ替わったり1件消えたりすると、React は「2番目の要素が別のデータに変わった」のか「1番目が消えて全体が1つ上がった」のかを、見た目だけからは区別できません。

key はその区別のために付ける印です。key があると、React は同じ key の要素を同じものとして追いかけ、消えた1件ぶんだけを取り除きます。key が無いと並び順で機械的に比べるので、入力中の文字やチェックの状態が別の行にずれて残る、という分かりにくいバグが起きます。

何を key にするか

一覧の中で重複しない値を使います。今回の作品データなら work.id が最適です。key は兄弟の中だけで一意ならよく、ページ全体で唯一である必要はありません。

配列の添字を key={index} とするのは最後の手段です。並べ替えも削除もしない一覧なら動きますが、先頭に1件足しただけで全部の添字がずれて、key が印の役目を果たさなくなります。タイトルのように後から変わる値や、Math.random() のように描くたびに変わる値も使ってはいけません。毎回すべてが「別のもの」になり、React が全部作り直します。

key は画面には出ません

key は React が内部で使う印なので、HTML の属性としては出力されません。ブラウザの検証ツールで見ても key は見当たりません。もし id を画面側でも使いたいなら、data-work-id のような data- 属性を別に付けます。こちらは普通の属性として出力されます。

演習

一覧に key を付けて警告を消し、あわせて確認用の data-work-id も出します。

ヒント

App.jsx
App.jsx
プレビュー

できているか

  • work-card が3枚並んでいる
  • 1枚目のカードの data-work-id が 1 になっている
  • 3枚目のカードの data-work-id が 3 になっている
  • 3枚目に「写真ギャラリー」が表示されている