Reactの関数にコンポーネントの配列を返す時はkeyに要注意
Reactのwarningを解消しようと試行錯誤していた所、アンチパターンになりそうな書き方を見つけたので紹介します。
「コンポーネントを配列に格納したい時は各コンポーネントに必ずkeyを割り振ろう」という話です。
環境
- React 16.2.0
コンポーネントの配列
React上で複数のコンポーネントをまとめて扱いたい時に使います。
例えば、以下のような書き方をすることでComponentA,B,Cをひとまとめにして返すことができます。
anyFunction(){
ver list = [];
list.push(<ComponentA />);
list.push(<ComponentB />);
list.push(<ComponentC />);
return list;
}
実際には配列やmapから渡して繰り返しコンポーネントを生成する場面での使い道のほうが多いです。
(テーブルの列を生成する時など)
Object.keys(this.props.data).forEach((key, index) => {
list.push(
<Checkbox
key={this.props.data[key].id}
id={this.props.data[key].id}
label={this.props.data[key].label}
/>,
);
});
ハマった所
しかし、ブラウザで画面を開いてコンソールを開くと下記のようなWarningが出ることがあります。
Warning: Each child in an array or iterator should have a unique "key" prop.
Check the render method of `ParentComponent`. See https://fb.me/react-warning-keys for more information.
直接keyを指定しないと出るようです。
なので、最初のコードは
anyFunction(){
ver list = [];
list.push(<ComponentA key={"a"} />);
list.push(<ComponentB key={"b"} />);
list.push(<ComponentC key={"c"} />);
return list;
}
と書かないとwarningが出ます。
もしくは、returnを使うとkey値を指定しなくてもよくなります。
anyFunction(){
ver list = [];
list.push(<ComponentA key={"a"} />);
return list;
}
と、以下のコードが同じような意味合いです。
anyFunction(){
return(
<ComponentA />
);
}
配列にコンポーネントを持たせるときは(1個であっても)必ずkeyを割り振りましょう、というReactの作法。
returnを使う場合は自動でkeyを割り振ってくれることもありますが、それ以外はkeyを明示したほうがよさそうです。
- 直接returnする
- そもそも配列で複数コンポーネントを渡さない
ようにするとこのwarningを回避できる+Reactと相性の良いコードになりそうです。
今回のように直接コンポーネントが置かれているとわかりやすいですが、コードによっては色々ネストして、
import Table from 'react-bootstrap';
//略
list.push(
<Table>
<tbody key={'tbody_key'}>
<tr key={"event_start_date_column"}>
<td><ComponentA key={aaa}/></td>
<td><ComponentB key={bbb}/></td>
<td>ccc</td>
</tr>
// 略
</Table>
);
//略
のようになると、うっかり「Tableにkey入れるの忘れてた!」とハマることがあるので、
1関数で1コンポーネントをreturnして配列を返すのを避けるようにしたほうが良い設計になるのかな、と思いました。
まとめ
Reactの配列はObjectの配列として扱われるので、コンポーネントとして扱われず、自動的にkeyが割り振られないのかと。
一方で、return(<Component />);
の場合は自動的にkeyを割り振ってくれるため、わざわざreturn(<Component key={'component_key'} />);
のような書き方をしなくてOKらしい。
今回紹介したwarningを見かけた方へ解決の参考になれば幸いです。
参考
- (React.jsの地味だけど重要なkeyについて)[https://qiita.com/koba04/items/a4d23245d246c53cd49d]
- (Reactでユニークなkey指定の警告が出たときの対処法)[https://hacknote.jp/archives/25626/]