なぜReactの「key」はあなたの人生を救うのか?リストレンダリングの深淵
現場でコードを書いていると、「とりあえず `map` で回して `key` に `index` 入れておけば動くでしょ」という場面に出くわすことがよくある。正直に言おう、それは「地雷を埋め込んでいるのと同義」だ。
今回は、Reactのリストレンダリングにおける「key」の真の役割と、差分検出アルゴリズム(Reconciliation)の裏側について、中級者の一歩先を行く視点で深掘りしていく。
—
1. 仮想DOMと「差分検出」という名の職人芸
Reactが高速なのは、DOMを直接いじらないから……というのは半分正解で半分は誤解だ。真髄は、「最小限のDOM操作で済むように、賢く差分を見抜くアルゴリズム」にある。
Reactは `render` のたびに新しい仮想DOMツリーを構築し、前のツリーと比較する。この「差分検出(Diffing)」において、リストのような動的な要素を扱うとき、Reactは非常に困る。
「このリストの3番目の要素が削除されたとき、残りの要素が移動したのか、それとも中身が書き換わっただけなのか?」
これを人間がパッと見てわかるように、Reactに教えるためのIDタグ、それが `key` だ。
—
2. なぜ「index」をkeyにしてはいけないのか?
これ、新人研修でよく見る光景だが、配列のインデックス(`index`)を `key` にするのはアンチパターンだ。
もしリストの先頭に要素を追加した場合、インデックスはすべてズレる。Reactは「あ、全部の要素が入れ替わったんだな」と勘違いし、DOMを再生成する。これではせっかくの仮想DOMの恩恵が台無しだし、もっと深刻なのはコンポーネントの内部状態(State)が壊れることだ。
例えば、入力フォームがあるリストでインデックスをkeyにすると、削除や追加をした瞬間に、前の行の入力内容が次の行に引き継がれるというバグが発生する。これはReactのせいではない。我々が「識別子」を正しく渡さなかったせいだ。
—
3. 実務で使うべき「正しいリストレンダリング」
現場では、「永続的な一意のID」をバックエンドから受け取ることが鉄則だ。もし存在しないなら、フロントエンド側で生成するのではなく、データ構造そのものを見直す勇気を持ってほしい。
以下に、実務で使える「再利用可能なリストコンポーネント」の構成例を示す。
import React from ‘react’;
/
- 実務レベルのリストレンダリング例
- ポイント:keyにはindexではなく、データ固有のidを使用する
/
const UserList = ({ users }) => {
return (
-
{users.map((user) => (
-
))}
);
};
// コンポーネントを分割することで、Reactはkeyごとに
// どのコンポーネントが更新されたかをより正確に追跡できる
const UserItem = ({ name }) => {
// ここで独自のStateや副作用を持つ場合でも、
// keyが正しければ状態の不整合は起きない
return {name};
};
export default UserList;
このコードの「賢い」ところ
- keyの安定性: `user.id` はデータが削除されない限り不変だ。ReactはDOMツリーの移動を正確にトレースできる。
- 関心の分離: `UserItem` に責務を分離することで、リスト全体を再レンダリングせず、変更のあった行だけをピンポイントで更新させる「メモ化(React.memo)」の土台を作っている。
—
4. シニアからのアドバイス:現場での判断基準
最後に、現場で迷った時の判断指針を伝えておく。
1. データにIDがない場合:
- APIのレスポンスが悪いなら、バックエンドチームと相談してIDを追加してもらうのが一番の近道だ。
- どうしても無理なら、データ生成時に `crypto.randomUUID()` 等で一時IDを付与するが、これは最後の手段だ。
2. 静的なリスト(並び替えが絶対に発生しない)なら:
- 例外的に `index` を許容することもある。だが、コードレビューで「なぜここで `index` を使ったか」を論理的に説明できないなら、最初から書かない方が身のためだ。
3. パフォーマンスの罠:
- `key` に `Math.random()` を使うのは絶対NGだ。レンダリングのたびにkeyが変わり、リスト全体が毎回再構築されるため、パフォーマンスは最悪になる。
—
まとめ:Reactは「正直」に振る舞え
Reactは、君たちが思っている以上に「正直」なライブラリだ。君たちが正しい情報を与えれば、驚くほど効率的に仕事をしてくれる。逆に、適当な情報を与えれば、その「嘘」のツケをパフォーマンス低下やバグという形で返してくる。
`key` を正しく選ぶことは、ただの技術的なお作法じゃない。「このデータはこれである」という設計者の意志を、Reactに正しく伝えるコミュニケーションなんだ。
明日からのコードレビューでは、ぜひ `key={index}` という記述を見つけたら、「なぜこれが必要なのか?」「本当にこれで将来的な要件変更に耐えられるのか?」をチームで議論してみてほしい。そこから、君たちのプロダクトは一段階上のクオリティへ進化するはずだ。

コメント