Warning: Each child in a list should have a unique "key" prop.
React needs a unique key on every element in a list so it can efficiently update the DOM when items change.
The Quick Fix
// β No key
{items.map(item => <li>{item.name}</li>)}
// β
With key
{items.map(item => <li key={item.id}>{item.name}</li>)}
Use a unique, stable identifier from your data β usually an id field.
Why Keys Matter
Without keys, React re-renders the entire list when one item changes. With keys, React knows exactly which item changed and only updates that one. This matters for:
- Performance (large lists)
- Preserving component state (inputs, animations)
- Correct behavior when items are reordered or deleted
Why Index as Key Is Bad
// β Avoid this
{items.map((item, index) => <li key={index}>{item.name}</li>)}
Index as key breaks when you:
- Reorder items β React thinks item 0 is still item 0, even though the data changed
- Delete items β all items after the deleted one get wrong keys
- Add items to the beginning β every item gets a new key, causing full re-render
When index is OK: Static lists that never change order and never have items added/removed. But even then, a real ID is better.
How to Pick Good Keys
Best: Use a unique ID from your data
// Database records
{users.map(user => <UserCard key={user.id} user={user} />)}
// API responses
{posts.map(post => <Post key={post.slug} post={post} />)}
If no ID exists: Generate one when creating the data
// When adding items
const newItem = { id: crypto.randomUUID(), name: "New item" };
setItems([...items, newItem]);
Donβt generate keys during render:
// β New key every render = full re-mount every time
{items.map(item => <li key={Math.random()}>{item.name}</li>)}
// β Same problem
{items.map(item => <li key={crypto.randomUUID()}>{item.name}</li>)}
Nested Lists
Each list needs its own keys, but keys only need to be unique among siblings:
{categories.map(cat => (
<div key={cat.id}>
<h2>{cat.name}</h2>
<ul>
{cat.items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
))}
cat.id and item.id can overlap β theyβre in different lists.
Common Mistakes
Key on the wrong element:
// β Key should be on the outermost element in the map
{items.map(item => (
<div>
<span key={item.id}>{item.name}</span>
</div>
))}
// β
Key on the outer element
{items.map(item => (
<div key={item.id}>
<span>{item.name}</span>
</div>
))}
Using non-unique values:
// β Multiple users might have the same name
{users.map(user => <li key={user.name}>{user.name}</li>)}
// β
Use the unique ID
{users.map(user => <li key={user.id}>{user.name}</li>)}