Rendering and data flow

Give list items stable keys

Help React match each rendered item with the same data item across insertions, removals, and reordering.

A key tells React which item is which among siblings across renders.

{tasks.map(task => (
  <Task key={task.id} task={task} />
))}

When tasks move, React uses each ID to keep component and DOM state with the correct task. The checkbox state stays with the task the user checked, not with a position in the list.

Array indexes are unsafe when items can be inserted, removed, sorted, or filtered. If the first task is removed, the item now at index zero can inherit the previous first component’s input state. The text in the field no longer matches the task title next to it.

Generate IDs when data is created, not while rendering. key={Math.random()} changes identity on every render and forces React to recreate the subtree. Inputs lose focus. Animations restart. Performance suffers for no reason.

Keys need to be unique only among siblings. The same task ID can appear in a separate list elsewhere in the tree.

key is for React and is not passed as a normal prop. Pass id={task.id} separately when the component needs it inside Task.

If React warns about missing keys, the fix is always on the outermost element returned from map(). Adding a key to a parent div that wraps the mapped items is not enough when each item is nested deeper.

Fragment keys work the same way when map() returns a Fragment. Put the key on <Fragment key={task.id}> rather than on a child inside it.

Build a list with editable inputs, then sort it. Compare stable IDs with index keys and watch which text stays with each item. The difference is immediate once you reorder or delete from the middle.

Lesson completed