Reactアプリでの「Warning: Each child in a list should have a unique “key” prop.」の回避はコンポーネントの呼び出され側ではなく呼び出し側で行う

2021.10.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、ReactアプリでのWarning: Each child in a list should have a unique "key" prop.の回避はコンポーネントの呼び出され側ではなく呼び出し側で行おう、という内容です。

事象

下記のように呼び出し側のコンポーネントからmap()を使用して呼び出され側のコンポーネントのリストを作成するReactの実装があります。

import React from 'react';

type SelectButtonProps = { buttonNumber: number };

//呼び出され側
const ButtonList: React.FC<SelectButtonProps> = (props) => {
  return (
    <div>
      <button>No. {props.buttonNumber}</button>
    </div>
  );
};

//呼び出し側
export const App: React.FC = () => {
  const ary: number[] = [1, 2, 3, 4, 5];

  return (
    <>
      {ary.map((d) => (
        <ButtonList buttonNumber={d} />
      ))}
    </>
  );
};

実装のデモを見ると、Warning: Each child in a list should have a unique "key" prop.というWarningがコンソールに出力されているかと思います。

これはReactが要素のリスト内で変更、追加、削除されたアイテムを識別するために、ユニークなID値を持つkeyプロパティを設定することが推奨されているためです。

解決できなかった対処方法

というわけでWarning回避のために呼び出され側のコンポーネントの要素にkeyプロパティを持たせてみます。

import React from 'react';

type SelectButtonProps = { buttonNumber: number };

//呼び出され側
const ButtonList: React.FC<SelectButtonProps> = (props) => {
  return (
    <div key={props.buttonNumber}>
      <button>No. {props.buttonNumber}</button>
    </div>
  );
};

//呼び出し側
export const App: React.FC = () => {
  const ary: number[] = [1, 2, 3, 4, 5];

  return (
    <>
      {ary.map((d) => (
        <ButtonList buttonNumber={d} />
      ))}
    </>
  );
};

しかしWarningは消えていません。この方法だと回避できないようです。

解決できた対処方法

次に呼び出し側のコンポーネントの要素にkeyプロパティを持たせてみます。

import React from 'react';

type SelectButtonProps = { buttonNumber: number };

//呼び出され側
const ButtonList: React.FC<SelectButtonProps> = (props) => {
  return (
    <div>
      <button>No. {props.buttonNumber}</button>
    </div>
  );
};

//呼び出し側
export const App: React.FC = () => {
  const ary: number[] = [1, 2, 3, 4, 5];

  return (
    <>
      {ary.map((d) => (
        <ButtonList buttonNumber={d} key={d} />
      ))}
    </>
  );
};

すると今度はWarningを回避することができました。

参考

以上