Lists and keys
Say you're building a to-do list: a handful of items, each with its own text, pulled from an array of todo objects. React doesn't have a special list component for turning that array into markup. You use plain JavaScript's map to turn each item into a piece of JSX, and React renders the results.
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
)
}Rendering a list with map
That todos array usually arrives as a prop passed down from a parent component that owns the actual data. todos.map walks the array and returns one <li> for each todo. The curly braces around it drop that array of JSX elements straight into the <ul>, the same way you'd drop in a single expression. Each <li> also gets a key prop, set to todo.id. That part isn't optional if you want the list to behave correctly: skip it, and React still renders the list, but it logs a console warning, and the reordering bugs described below become real risks the first time the list changes shape.
A key is how React tells list items apart from one render to the next. It has to be unique among its siblings, so no two <li> elements in this list share a key, and it has to be stable, meaning the same todo gets the same key every time the list re-renders. An id from your data, like todo.id, is exactly that: it belongs to the todo, not to its position in the array, so it stays put even if the list around it changes.
Why the array index makes a poor key
That last point is why the array index makes a poor key. It's tempting, since every array already has one:
{todos.map((todo, index) => (
<li key={index}>{todo.text}</li>
))}This works fine as long as the list never reorders, and never has items inserted or deleted. The moment it does, the index stops matching the item it used to point to. Delete the first todo and every remaining item shifts up one index, so React sees the same keys attached to different todos. If any of those list items hold their own state, like a checkbox mid-edit or an input someone's typing into, that state stays attached to the index and ends up on the wrong row. Treat the index as a fallback for lists that are static and never reorder. Reach for a real id everywhere else.
map, give each one a key, and use a real id from your data, not its position in the array. The key is how React keeps track of which element is which between renders, and an id that belongs to the item stays correct even if the list gets reordered. Next up: State, where a component starts remembering things between renders.

