Reactで複数の要素を表示する際に、map関数を利用して配列からリストを生成するのはよくあるパターンです。しかし、配列の要素をレンダリングする際、特に動的なコンテンツ(増減や順序変更が発生するリストなど)において、Reactは各要素を追跡して効率的にレンダリングを管理する必要があります。このとき、keyという一意の識別子を設定しないと、以下のような警告がコンソールに表示されます。
Warning: Each child in a list should have a unique "key" prop.
この警告は、各リスト要素にkeyが設定されていない場合に表示されます。keyプロパティは、Reactがリストの各項目を特定し、効率的にレンダリングの差分を計算するための重要な要素です。
なぜkeyが必要なのか?
keyはReactにとって、どの要素が追加、削除、または変更されたかを識別するために必要です。例えば、以下のようなシナリオを考えてみましょう:
- ユーザーがリストに新しい項目を追加する
- リストの項目が並べ替えられる
- 特定の項目が削除される
これらの変更に対してReactが適切に対応しないと、パフォーマンスが低下したり、意図しないレンダリングが行われたりします。keyがないと、Reactはすべての要素を無条件に再レンダリングする可能性が高くなりますが、keyが正しく設定されている場合、必要な要素だけを最小限に再レンダリングすることでパフォーマンスが向上します。
keyプロパティの使い方
次に、具体的にmapを使ってリストを表示する例
const persons = ["Tom", "Jiro", "Taro"];
const Example = () => {
return (
<>
<ul>
{/* map関数を使用して配列をループし、リスト要素を作成 */}
{persons.map((person) => (
// 各リスト要素には必ず一意の key プロパティを設定
<li key={person}>Hello, {person}</li>
))}
</ul>
</>
);
};
export default Example;
keyに一意の値を設定する方法
-
単純な配列の場合:配列内の値自体がユニークであれば、上記の例のように値をkeyに設定できます。この場合、personが一意であることが前提です。
-
重複の可能性がある場合:リストの要素に重複がある場合や、要素が動的に増減する場合には、インデックスを使うことができます。ただし、リストの順番が変わる可能性がある場合は、インデックスは推奨されません。順序の変更が発生すると、インデックスが正確な追跡を妨げるためです。
{persons.map((person, index) => (
<li key={index}>Hello, {person}</li>
))}
- オブジェクトの場合:オブジェクトの配列をレンダリングする場合、各オブジェクトが持つ一意のプロパティ(例えばidなど)をkeyに使用します。
const persons = [
{ id: 1, name: "Tom" },
{ id: 2, name: "Jiro" },
{ id: 3, name: "Taro" },
];
const Example = () => {
return (
<ul>
{persons.map((person) => (
<li key={person.id}>Hello, {person.name}</li>
))}
</ul>
);
};
まとめ
- keyプロパティは、Reactにおいてリストの各要素を効率的に追跡するために必要
- keyには配列内の要素が持つ一意の値を使用するのが理想的
- 配列のインデックスをkeyに使用するのは、リストの順序が変わらない場合に限り有効ですが、通常は推奨されない
- keyが正しく設定されていないと、パフォーマンスの低下や意図しない再レンダリングが発生する可能性あり