The React key warning appears when a list is rendered without a stable key prop on each item. Keys let React match each item to its previous render, so a stable ID from your data fixes the warning and the bugs it hides.
Why React needs keys
When a list reorders, inserts, or deletes items, React needs to know which DOM node belongs to which item. Without keys it falls back to array position, so moving an item can misplace its state. That is why a missing key shows up as a warning even when the list renders correctly at first glance.
A well-chosen key identifies an item for its whole lifetime, even when its position changes. That is why the key must come from the data and not from the array position.
Add a stable key
Here is a list that renders without keys.
import { useState } from "react";
export default function TaskList() {
const [tasks] = useState([
{ id: 1, title: "Write tests" },
{ id: 2, title: "Ship it" },
]);
return (
<ul>
{tasks.map((task) => (
<li>{task.title}</li>
))}
</ul>
);
}React logs "Each child in a list should have a unique key prop." Add a key from the data so React can track each item across renders.
{tasks.map((task) => (
<li key={task.id}>{task.title}</li>
))}The warning disappears, and React can now track each task when the list changes, keeping its state attached to the right row. For the full list rendering workflow, see how to render lists in React with map.
Rules of keys
- Keys must be unique among siblings. The same key can appear in a different array.
- Keys must not change. Do not generate them during render.
- Keys are not passed as props. Pass an ID separately if the component needs it.
These rules exist so React can match the same item across renders without guessing.
Why index and random keys break
Using the array index as the key is the same as using no key, and it causes bugs when the list reorders or an item is removed. Generating a key with Math.random() creates a new key every render, so React remounts every item and loses its state. Both failures show up as lost input, broken focus, or replayed animations, which are hard to trace back to a key.
Use a database ID when the data has one. For locally generated data, use an incrementing counter or crypto.randomUUID() when you create the item. See how to remove, replace, and reorder array items in state for updates that depend on stable identity.
The ID only needs to be unique among siblings, so a counter scoped to the list is enough.
Handle empty lists too
A key only helps when there are items. When the list is empty, show a fallback so the empty state is deliberate rather than a blank screen, matching the same pattern as an error or loading state.
Rune AI
Key Insights
- Every item in a rendered array needs a key.
- Use a stable ID from the data, not the array index.
- Keys must be unique among siblings.
- Do not generate keys during render.
- Index is fine only for lists that never reorder.
Frequently Asked Questions
Is index as a key always wrong?
Can I generate a key with Math.random?
Conclusion
The unique key warning means a list is missing a stable key on each item. Use an ID from the data, keep keys unique among siblings, and avoid index and random keys.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.