Back to the blog
Reactยท Aug 3, 2026ยท 6 min read

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.

#react#keys#lists#reconciliation

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.