Keys & Lists
The problem
When a list of items changes — one is added, removed, or reordered — reconciliation needs a way to tell which rendered elements correspond to which data items across renders, or it will guess wrong and produce visible glitches or wasted DOM operations.
Why now
The virtual DOM and reconciliation already established that React diffs trees to minimize DOM changes, but diffing a list by position alone breaks the moment an item is removed from the middle — every item after it shifts position and looks 'changed' even though it didn't. Keys are the missing piece of identity information that fixes this.
Mental model
A key tells reconciliation 'this specific rendered element corresponds to this specific data item, regardless of its position in the list' — without it, React's default guess is array index, which silently breaks the moment items are inserted, removed, or reordered anywhere but the very end.
Requires
- The Virtual DOM & ReconciliationReact
Keys exist specifically to give reconciliation's diffing algorithm the identity information it can't infer on its own; you need reconciliation's diffing behavior already understood before keys' purpose is clear.
- Arrays & ListsProgramming Fundamentals
Rendering a list of components from an array is a direct application of iterating a sequence — the same array operations already covered, applied to produce UI elements instead of plain values.
Used in
- Every list of components rendered from an array (.map() over data)
- Form state bugs caused by using array index as a key when items can be reordered
- Animation libraries relying on stable keys to track elements across reorders
- React's console warning when a list is rendered without keys at all
Projects
- Render a reorderable list using array index as the key, then swap two items and observe an input field's value staying in the wrong place — then fix it with a stable unique key
- Explain, with a before/after diagram, why index-based keys break specifically on insertion/removal but work fine for a static, never-reordered list
Examples
- items.map((item, i) => <Item key={i} />) breaks visibly if an item is removed from the middle of the list — use item.id instead
- A list of chat messages keyed by message ID keeps each message's local state (like an 'edited' indicator) attached to the correct message even as new ones arrive
Resources
Mastery checklist
- I can explain what problem keys solve in reconciliation
- I can explain why array index as a key breaks for reorderable or filterable lists
- I can choose a stable, unique key from real data instead of index
- I can diagnose a list-related bug (misplaced state, wrong item highlighted) as a missing or incorrect key