配列でmapを使う時はkeyの値を適切に設定しよう

Reactでmapを使う時は一意に決まるkeyを設定してあげないといけません。

また、このmapのkeyの設定方法にはよくやってしまいがちなアンチパターンも存在します。

今回は基本的な使い方やアンチパターンについて紹介していこうと思います。

mapについて

まずはmapについて基本的な部分を始めに書いていきたいと思います。

良いパターン:サンプルコード

まずは良いパターンからです。

Reactで配列をmapで正しくkeyを設定した場合はこのようになります。

サンプルコードでは社員リストの配列を社員ID、社員名の一覧を表示するといったものですね。

今回の場合だとkeyに社員ID(配列内で一意に決まる文字列)を設定しています。

const MapExample = () => {

    const employees = [
        {
            id: "AAA",
            name: "Tanaka"
        },
        {
            id: "BBB",
            name: "Suzuki"
        },
        {
            id: "CCC",
            name: "Sato"
        }
    ];

    return (
        <div>
            {employees.map((employee) => (
                <div key={employee.id}>
                    <p>ID: {employee.id}</p>
                    <p>社員名: {employee.name}</p>
                </div>
            ))}
        </div>
    )
}

ポイント

  1. map内の兄弟間で一意の文字列をkeyに設定する
  2. map内での最上位の親要素へkeyを設定する
  3. keyに設定する値は配列内の要素で一意になる値があればそれを使う

簡単にまとめるとこのようなポイントを押さえておけば良いです。

しかし、3に関しては例外もあります。こちらについてはアンチパターンになりうる項目となりますので次に説明していきたいと思います。

アンチパターンについて(不適切なコード)

簡単に説明すると配列内に一意の文字列が存在するにもかかわらずmapのindexをkeyに設定しないほうが良いです。

これはパフォーマンスに悪い影響を与え、コンポーネントの状態に問題を起こす可能性があるとReact公式ドキュメントでも言及されています。

アンチパターン:サンプルコード

mapのindexの使い方に着目してください。

実際にこの方法でもエラーやワーニングはでることはありませんが、思わぬ悪影響がある可能性が極力やらないようにしたほうが良いです。

// map部分以外省略

{employees.map((employee, index) => (
    <div key={index}>
        <p>ID: {employee.id}</p>
        <p>社員名: {employee.name}</p>
    </div>
))}

なぜindexをkeyに設定してはいけないのか

こちらで紹介されているkey としてインデックスを用いる際の悪影響についての詳しい解説が分かりやすいと思いました。

この中に動作を確認することができるサンプルコードの紹介がありますので実際に動きを確認してみると良いと思います。

実際に動作を試してみると、リストの先頭へ順にアイテムを追加するシンプルなものですがindexをkeyに使っている場合は入力した内容とインプット要素がずれていってしまうことが分かりますね。

まとめ

些細な違いから大きな不具合を発生させてしまうこともありますので、しっかりと理解して正しくコードを書いていきましょう。