Reactの「key」を制する者は、レンダリングの深淵を制す
やあ。今日はReactを触る上で避けては通れない、けれど意外と「なんとなく」で済まされがちなテーマ、`key`プロパティについて話をしようか。
中級クラスのエンジニアなら、一度は「`key`に配列のインデックスを使ったらWarningが出た」なんて経験があるはずだ。でも、なぜそれがダメなのか、ブラウザの裏側で何が起きているのかを論理的に語れるだろうか?
今日は、Reactの仮想DOMがどうやってリストを追いかけているのか、その泥臭い裏側を紐解いていく。
—
1. なぜReactは「key」を執拗に求めるのか?
Reactが高速な理由の一つは、「差分検出アルゴリズム(Reconciliation)」にある。仮想DOMツリーを比較して、変更が必要な最小限のノードだけを実DOMに反映させる仕組みだ。
ここで問題になるのがリストだ。Reactは、配列の中身が入れ替わったり、途中に要素が挿入されたりしたとき、それが「何者なのか」を識別できないと、効率的にDOMを更新できない。
`key`は、Reactにとっての「名札」だ。これがなければ、Reactは「前のリストの1番目の要素と、今のリストの1番目の要素が同じものか?」を推測するしかない。この推測が外れると、DOMの破棄と再生成が走り、入力状態の消失や、アニメーションの不自然な挙動、そしてパフォーマンスの劇的な悪化を招くことになる。
2. インデックス(index)をkeyにしてはいけない「残酷な真実」
多くの初学者が陥る罠がこれだ。「とりあえず`index`を入れておけばエラーは消える」という思考。だが、それは時限爆弾を埋め込んでいるのと同義だ。
なぜindexが危険なのか?
リストが「静的」であるなら問題はない。しかし、リストの並び順がソートされたり、要素が削除・挿入されたりする瞬間、インデックスは「中身とは無関係な番号」へと成り下がる。
例えば、`[A, B, C]`というリストがあるとする。
1. Bを削除すると、Cは自動的にインデックスが「1」から「0」に繰り上がる。
2. Reactは「お、インデックス0はAからCに変わったな。じゃあ内容を書き換えよう」と判断する。
3. もしそのコンポーネントが内部状態(inputのフォーカスやアニメーション状態)を持っていたら、それが別の要素に引き継がれてしまい、バグの温床になる。
3. 実践:正しくkeyを扱うためのベストプラクティス
現場で最も安全なのは、バックエンドから送られてくる一意なID(UUIDやDBの主キー)を使うことだ。もし手元にない場合は、フロントエンド側で生成することも検討しよう。
以下に、実務で使える「やってはいけない例」と「正しい実装例」を対比させたコードを置いておく。
// — 実務でよく見る「危険な」パターン —
// 要素を削除したり並び替えると、ReactがDOMの識別を誤り、バグの原因になります。
const TodoList = ({ items }) => {
return (
-
{items.map((item, index) => (
- {item.text}
// 絶対NG:インデックスをkeyにする
))}
);
};
// — 推奨される「安全な」パターン —
// 一意なIDが存在しない場合、レンダリング前に生成するか、
// データそのものが持つ永続的なIDを使用します。
const TodoListCorrect = ({ items }) => {
return (
-
{items.map((item) => (
-
{item.text}
// OK:アイテム固有のIDをkeyに設定
// これにより、Reactは要素が移動しても「これは同じものだ」と追跡できる
))}
);
};
4. シニアとしてのアドバイス:どうしてもIDがないときは?
たまに「外部APIの都合でIDがない」という泣きたくなる状況はあるだろう。そんな時は、`nanoid`や`crypto.randomUUID()`を使って、データフェッチ時にIDを付与してしまうのが定石だ。
ただし、レンダリング関数の中でIDを生成してはいけない。これだけは鉄則だ。
// ❌ やってはいけない実装
{items.map(item =>
// これをやると、レンダリングのたびにkeyが変わるため、
// 毎回DOMが全破棄・再生成されてしまい、パフォーマンスが死ぬ。
まとめ:keyは「アイデンティティ」である
`key`プロパティは、単なるReactの仕様上の要件ではない。それは「データの一貫性を保つための生命線」だ。
- 一意であること: 同じリスト内で絶対に重複しないこと。
- 不変であること: アイテムが生きている限り、keyは変わらないこと。
この二つを意識するだけで、君が書くアプリケーションの堅牢性は段違いに向上するはずだ。次のPR(プルリクエスト)を送るときは、ぜひ「このkeyは本当に一意で不変か?」と自問自答してみてほしい。
現場からは以上だ。また何か躓いたら、いつでも聞きに来るといい。

コメント