React's 'unique key prop' warning: why index keys break your UI
'Each child in a list should have a unique key' is more than lint noise - the wrong key silently corrupts input state and animations when lists reorder. What keys actually do, and how to choose them.
Most developers silence the key warning with key={index} and move on. The warning goes away; the bug stays. Keys are how React matches list items across renders, and an index key tells React 'position 2 is always the same item' - which becomes a lie the moment you insert, delete, sort, or filter.
What goes wrong with index keys - concretely
Render a list of rows, each containing an uncontrolled input. Type into row 1, then delete row 0. React sees the same keys (0, 1, ...) and reuses the DOM: your typed text now sits next to the wrong row's data. The same mechanism scrambles checkbox state, focus, CSS transitions, and component-local state on reorder. It's one of the hardest bugs to reproduce because it only appears after mutation.
// โ Breaks on insert/delete/sort
{todos.map((todo, i) => <TodoRow key={i} todo={todo} />)}
// โ
Stable identity from your data
{todos.map((todo) => <TodoRow key={todo.id} todo={todo} />)}Choosing a key when there's no id
- A unique field or combination from the data itself - email, slug, `${userId}-${date}`.
- Generate ids when the item is CREATED (crypto.randomUUID() in the add handler), then keep them - never during render.
- Index is acceptable only when the list never reorders, never filters, and items have no state - a static footer nav, say.
- Never key={Math.random()} - a new key every render remounts every item, destroying state and performance in one move.
Keys as a feature: resetting state on purpose
// Changing the key remounts the component - a clean state reset
<ProfileForm key={selectedUserId} userId={selectedUserId} />The same mechanism that makes wrong keys dangerous makes deliberate keys powerful. Keying a form by the record it edits guarantees fresh state per record - no manual useEffect resets, no leftover validation errors from the previous user.
A key answers one question: 'is this the same item as last render?' If your key can't answer that truthfully after a sort or delete, it's the wrong key.
Written by Appesto Engineering.