← Debugging Guides

阅读中文版本

React Missing key Prop — List Items Warning

Fix the "Each child in a list should have a unique key" warning by assigning stable keys and understanding why index keys cause bugs.

beginnerdebuggingreactlistskeys

Symptoms

  • Console warns "Each child in a list should have a unique key prop"
  • Reordering a list shows the wrong item state
  • Input values jump to the wrong row after deletion

Possible causes

  • The map callback returns elements without a key
  • The key uses the array index while the list can reorder or filter
  • The key is not unique, such as a duplicate id

Diagnosis steps

Locate maps without keys

grep -rn ".map(.*=>" src/ | grep -v "key="

Interpretation

Every map returning JSX needs a key on the outermost element it returns.

Switch to a stable identifier

git diff src/components/List.jsx

Interpretation

Using item.id instead of index fixes the state mix-up on reorder and delete.

Root cause

React uses keys to match elements between renders. Without keys, or with index keys on a reorderable list, React cannot tell which item moved, so it reuses the wrong DOM and state.

Fix

Give each rendered item a stable, unique key from the data (an id or slug), never the array index when the list can change order or length.

Risk note

Random keys force remounts every render, destroying state and performance; keys must be stable across renders.

Verify the fix

Reorder and delete items and confirm each row keeps its own state; the console warning should be gone.

Symptoms

When you hit “React Missing key Prop — List Items Warning”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.

Observed symptoms include:

  • Console warns “Each child in a list should have a unique key prop”
  • Reordering a list shows the wrong item state
  • Input values jump to the wrong row after deletion

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Locate maps without keys

grep -rn ".map(.*=>" src/ | grep -v "key="

Every map returning JSX needs a key on the outermost element it returns.

Step 2: Switch to a stable identifier

git diff src/components/List.jsx

Using item.id instead of index fixes the state mix-up on reorder and delete.

Likely contributors, in order of frequency:

  • The map callback returns elements without a key
  • The key uses the array index while the list can reorder or filter
  • The key is not unique, such as a duplicate id

Root Cause

React uses keys to match elements between renders. Without keys, or with index keys on a reorderable list, React cannot tell which item moved, so it reuses the wrong DOM and state.

The Fix

Give each rendered item a stable, unique key from the data (an id or slug), never the array index when the list can change order or length.

Watch out: Random keys force remounts every render, destroying state and performance; keys must be stable across renders.

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((t) => (
        <li key={t.id}>{t.text}</li> // stable id, not index
      ))}
    </ul>
  );
}

// ❌ key={index} breaks state on reorder/delete

Verify and Prevent

Reorder and delete items and confirm each row keeps its own state; the console warning should be gone.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.