やあ、Reactの世界へようこそ!
フロントエンドの深淵を覗き込んでいる君に、最初に出会う「ちょっとした壁」について話をしようと思う。
Reactを触り始めると、必ず一度はコンソールに真っ赤な文字で怒られるんだ。「`Each child in a list should have a unique “key” prop.`」ってね。これを見て「何だか怖いな」と萎縮してしまう人も多いけれど、実はこれ、Reactが君に「お願いだから、ちゃんと管理させてくれよ!」とヘルプを出しているだけなんだ。
今日は、この「key」という名の迷宮について、一緒に紐解いていこう。
—
1. なぜ「key」が必要なのか?:お買い物のレジをイメージしよう
まずは、仮想DOM(Reactの魔法の鏡)の仕組みを、近所のスーパーのレジで例えてみるよ。
君がスーパーで5人のお客さんのカゴを精算するとしよう。
もし、お客さんが全員「名札」をつけていなかったらどうなる? 並び順だけで判断していると、途中で誰かが割り込んだり、順番を入れ替えたりした瞬間に、レジ係(React)は大パニックだよね。「あれ? さっきまでここにいたAさんはどこに行ったんだ?」って。
Reactにおける「key」は、まさに「お客さんの背中につける名札」なんだ。
Reactは、画面を更新するときに「どこが変わったか」を最小限の労力で探し出そうとする。もし名札(key)があれば、どんなに順番が入れ替わっても「ああ、あの背中に『taro』と書かれた人は、3番目から1番目に移動しただけだな」と即座に理解できるんだ。
これがなければ、Reactは「全員入れ替わった!」と勘違いして、一度全員を追い出して、また全員を呼び直す……なんていう非効率なレンダリングをしてしまう。これがパフォーマンス低下の正体さ。
—
2. インデックス(index)をkeyにしてはいけない理由
初心者の方がよくやってしまうのが、`map`関数の第2引数である`index`(0, 1, 2…という連番)をそのままkeyにすることだ。
// ❌ やってはいけない例
{items.map((item, index) => (
))}
これ、一見動くから問題ないように思えるよね? でも、もし配列の途中に新しい要素を追加したり、順番を並び替えたりしたらどうなる?
例えば、一番上に新しい要素を追加したとする。すると、それまで「0番目」だった要素は「1番目」にズレるよね。名札が「0」から「1」に変わってしまうんだ。Reactからすれば「あれ? 0番目の人の名前が急に変わったぞ? 中身を全部書き換えなきゃ!」と余計な仕事が発生するし、最悪の場合、入力フォームの状態などがバグってしまうんだ。
「インデックスをkeyにするのは、席替えのたびに新しい座席番号を割り振るようなもの」。これじゃあ、誰がどこに座ったか追跡できないよね。
—
3. 正しい「key」の選び方
じゃあ、どうすればいいか。答えはシンプルだ。「そのデータ固有の、一生変わらないID」を使うことだよ。
データベースから取ってきたデータなら、必ず`id`(例:`user_123`)が付いているはずだよね。これを使うのが正解だ。
// ✅ 正解の例
{items.map((item) => (
// データベースのユニークなIDを使うのがベスト!
))}
もしデータにIDがない場合は、せめてその要素が持つ「固有の値」を使おう。例えば、「メールアドレス」や「ユーザー名」などがそれに当たるね。
どうしてもIDがない時は?
「どうしても外部のデータでIDがない!」ということもあるだろう。その場合は、データを作成するタイミングで「ユニークな文字列(UUIDなど)」を生成して付与してあげるのが、プロの現場での定石だ。無理やりindexで誤魔化すより、ずっと健全だよ。
—
最後に:ReactからのSOSを見逃さないで
Reactがコンソールで警告を出しているのは、君のコードが悪いからじゃない。「もっと賢く、もっと速く動けるポテンシャルが君のアプリにはあるんだよ!」と教えてくれているサインなんだ。
- keyは「名札」であること
- 順序が変わっても変わらない「固有のID」を選ぶこと
- indexの使用は、あくまで「配列が絶対に変化しない場合」に限定すること
この3つを頭の片隅に置いておくだけで、君の書くReactコードはぐっと安定して、プロフェッショナルな品質に近づくはずだ。
もし何かで躓いても大丈夫。最初はみんなここで悩むんだ。一歩ずつ、丁寧にコードと向き合っていけば、必ず「なるほど、こういうことだったのか!」と腑に落ちる瞬間が来るよ。
さあ、エディタを開いて、君のリストに素敵な名札をつけてあげよう。応援しているよ!

コメント