キーは、コレクションをレンダリングするための重要な側面です。 Reactはコンポーネントキーを使用して、何かが変更されるたびにコンポーネントのセット全体を再レンダリングするのではなく、コレクション内のどのコンポーネントを再レンダリングする必要があるかを判断します。 このシンプルで強力な機能は、Reactアプリをスッキリと保つのに役立ちます。これは良いことです。

キーは必須です

配列をループして一連のリストアイテムコンポーネントを作成する次のコードがあるとします。

const reptiles = ['alligator', 'crocodile', 'snake'];

const reptileComponents = reptiles.map((reptile) => {
  <li>
    {reptile}
  </li>
});

const container = document.createElement('div');
document.body.appendChild(container);
ReactROM.render(<ul>{reptileComponents}</ul>, container);

これにより、Reactは、配列またはイテレータの各子に一意のキーが必要であることを通知する警告をコンソールにスローします。

少なくとも今日では、すべてが正しくレンダリングされます。 通常、本番バンドルではこれらのタイプの警告が省略されているため、開発中は必ずこれらの警告に注意する必要があります。

Reactが今日キーレスコンポーネントを正しくレンダリングするからといって、Reactが将来キーレスコンポーネントを正しくレンダリングすることを意味するわけではありません。

前述のコードを修正するには、リストアイテムにkeyプロパティを含めるだけです。

const reptiles = ['alligator', 'crocodile', 'snake'];

const reptileComponents = reptiles.map((reptile) => {
  <li key={reptile}>
    {reptile}
  </li>
});

const container = document.createElement('div');
document.body.appendChild(container);
ReactROM.render(<ul>{reptileComponents</ul>, container);

キーは一意である必要がありますが、兄弟間でのみです

キーは、変更されたコンポーネントのみが再レンダリングされるようにするのに役立ちます。 どのコンポーネントが実際に変更されたかを追跡できる唯一の方法は、それらに一意のキーをタグ付けすることです。

幸い、キーの一意性はコレクション自体にのみ適用されます。 キーは、Reactアプリ全体で一意である必要はなく、コレクションの兄弟全体で一意である必要があります。

別のワニを追加して次のコードを実行すると、警告が表示されます。

const reptiles = ['alligator', 'crocodile', 'snake', 'alligator'];

const reptileComponents = reptiles.map((reptile) => {
  <li key={reptile}>
    {reptile}
  </li>
});

const container = document.createElement('div');
document.body.appendChild(container);
ReactROM.render(<ul>{reptileComponents}</ul>, container);

キーの欠如に関する警告が実際に問題を引き起こさないのと同様に、重複するキーがある場合でも、今日でも正しくレンダリングされます。 内部的には、一意のキーがないために、アプリの速度が低下する可能性のある追加の再レンダリングが発生している可能性があります。

ただし、警告を無視する必要があると言っているわけではありません。 警告には、将来的に状況が変わる可能性があること、およびYMMVが一意でないキーであるためにコンポーネントが重複または省略される可能性があることも記載されています。

この重複キーの問題を修正するには、値の代わりに配列のインデックスをキーとして含めるのが簡単です。

const reptiles = ['alligator', 'crocodile', 'snake', 'alligator'];

const reptileComponents = reptiles.map((reptile) => {
  <li key={index}>
    {reptile}
  </li>
});

const container = document.createElement('div');
document.body.appendChild(container);
ReactROM.render(<ul>{reptileComponents</ul>, container);

順序が固定された配列のピンチでは十分ですが、配列アイテムの順序が将来変更される可能性がある場合、これは最も理想的なソリューションではありません。

これらのシナリオでは、代わりに何らかの内部一意識別子(ID)を使用することをお勧めします。