「React の key に配列の添え字を使ってはいけない」理由を説明できますか?
リスト以外で key を使うべき場面をご存じですか?
今回は React の key を適切に扱えないと起こる問題を紹介します。
ダメな例のデモ
まず、key を適切に設定していない、keyをつけるべき場面を実際にご覧ください。
問題1: key をつけるべきなのにつけていない codesandbox.io
問題2: key を適切に設定していない(index で設定してしまっている) codesandbox.io
問題1: key をつけるべきなのにつけていない
recursing-fermi-6bm9c - CodeSandbox
確認手順:
- 「change」ボタンをクリックする
- 色名がすぐに Green へ変化する
- 画像のほうは以前のものがしばらく(新しい画像の読み込みが終わるまで)表示され続ける
このように色名と画像がズレるのは意図していません。
どうして起きるのか?
change ボタンを押したとき React からすると「img の src が変わっただけ」に見えます。 そのため、React は同じ img 要素を使って src だけ変えます。同じ img 要素なので、以前の画像がキャッシュされ、新しい画像を読み込むまで古い画像を表示し続けます。
解決方法: key を設定する
解決するには、React へ img 要素を新しい img 要素で置き換えるよう指示 すれば OK です。そして、ここで使うのが key prop です。key を使えば React に「img 要素が新しくなった」と伝えられます。新しい画像 URL がセットされた新しい img が追加されれば、古い画像が表示されることはありません。
問題2: key を適切に設定していない
zealous-lehmann-luycv - CodeSandbox
こちらは key に配列の添え字を渡してしまっているパターンです。要素を削除したときに問題が起こっています。
確認手順:
- 1つ目の delete ボタンを押す
- input の値が Blue のままになっている
どうして起きるのか?
これも先ほどの例と同じで、要素が削除されても React からすると「最後の要素が削除された」ように見えるため、1つ目の DOM を使いまわそうとするためです。
解決方法: 要素ごとにユニークな値を key にする
これを解決するには、要素ごとにユニークな値を使えば OK です。key は「ある要素と DOM の対応付けをしている」と考えれば腑に落ちるでしょう(間違えた例では index が同じなのだから input の値が変わらないのは当然)。
まとめ: コンポーネントが内部に状態を持っているときは key に気を付ける
見てきた例は2つとも、コンポーネントが内部に状態を持っていた(img と input)のが原因でした。内部の状態を引き継がせたくない場合は、しっかりと key を設定しましょう。
(もちろん各人が作った React コンポーネントも内部に状態を持っていれば同じような問題が起こります)