list要素のkeyにうっかりindexを指定してしまい、実務でハマったので教訓をまとめておきます。
「listのkeyなんてレンダリングを最適化してくれるだけでしょ?」と甘く考えていたところ、痛い目に会いました。
結論(今回の教訓)
list要素の"key"にはデータの主キー等の"ユニーク"かつ"不変"な値を設定すること!
参考:なぜ"ユニーク"かつ"不変"な値を設定する必要があるのか
reactがkeyの値で同一コンポーネントかどうかを識別しているため。
いろいろな方がまとめられているため、詳細はそちらを確認ください。
簡単に言うと、reactはkeyの値を元に要素の追加、変更、削除を追尾するため、keyにユニークな値を設定することで不要な再レンダリングを防ぐことができます。
また意図せずにindexを指定すると、↓のように思わぬバグに遭遇する可能性があります。
実務でハマった内容
バグが発生した機能
受注した契約情報の一覧ページ
<詳細>
・1ページあたり10件の契約を表示。
・各行に編集ボタンがある。
・編集ボタンを押下すると、その契約の受注金額を一覧上で編集できる。(ReactHookFormにより編集を実現)
「料金編集」を押すと、その行の料金が一覧上で編集できるようになります。
バグの概要
2頁目1行目の契約の編集ボタンを押下すると、1頁目1行目の契約の金額が表示される。
原因
list要素のkey
に配列のindex
を指定していたため、2頁目1行目(key=1
)が1頁目1行目(同じくkey=1
)を参照していた。
表示中の頁が何頁目であれ配列のindexは常に1~10。
そのためkey
にindex
を指定すると、1頁目1行目、2頁目1行目共にkey=1となる。
1頁目の表示時には、1行目の金額編集フォーム(RHFのdefaultValues)に1頁目1行目の契約の金額が正しく紐づけられる。
しかし2頁目に切り替えても、1行目はkey=1
であるためreactから既存の要素と認識されてしまい、要素の新規作成(defaultValuesの設定)が行われず、1頁目1行目の金額を参照するままとなってしまった。
対応内容
key
に契約情報の主キーを設定。
これによりページ切り替え時に各行が新規追加の要素として認識され、フォーム(defaultValues)に対応する契約の金額が正しく設定されるようになった。