Detailed explanation
Lists need keys because React must identify which rendered item corresponds to which item from the previous render. A list can change when items are inserted, removed, sorted, or filtered. Without a reliable identity, React may associate an existing component with the wrong data. A key provides that identity among sibling elements, helping React preserve the correct component state and update the interface consistently. This matters especially when rows contain editable inputs, expanded sections, or other local state.
During reconciliation, React compares the new element tree with the previous one. For list children, keys help it match old and new elements, while element type also determines whether an existing component can be reused. For example, {todos.map(t => <Todo key={t.id} data={t} />)} identifies each Todo using its data ID. If the todos move, React can retain their component instances and associated state rather than treating their positions as their identities. A stable key does not prevent a component from rendering again; it helps React decide whether to preserve or replace it.
A good key is stable across renders and unique within its sibling list. It does not need to be globally unique. Prefer an ID stored in the underlying data, and place the key on the element returned directly by map. React handles key specially, so it is not available as props.key inside Todo; pass the ID separately if the component needs it. Avoid generating keys with Math.random() during rendering, because changing keys makes React treat items as new, resetting state and recreating their rendered subtrees.
Array indexes are risky because they identify positions rather than records. If an item is inserted at the beginning, existing positions now represent different todos, so local state can appear on the wrong row. Index keys can be acceptable for genuinely static lists whose membership and order never change, but stable data IDs are usually clearer. Interviewers generally look for an explanation centred on identity and state correctness, not just performance. Missing keys do not necessarily recreate every item; React commonly falls back to positional matching, which is precisely what can cause incorrect state associations.
Key points to remember
- Keys give sibling list items stable identities between renders.
- React uses keys and element types to determine which components to preserve.
- Use stable data IDs, unique among siblings, on the elements returned directly by map.
- Stable keys preserve identity and state; they do not prevent re-renders.
- Avoid index keys for changing lists and randomly generated keys during rendering.
Common mistakes candidates make
- Saying keys are only a performance optimisation and ignoring state correctness.
- Using array indexes for lists that can be reordered, filtered, or have items inserted or removed.
- Putting the key inside the child component instead of on the mapped element, or expecting to read props.key.
Likely follow-up questions
Do keys need to be unique across the whole application?
No, keys only need to be unique among siblings in the same list. Two separate lists can safely use the same IDs as keys.
What happens when a component's key changes?
React treats it as a different component, unmounting the old instance and mounting a new one. Its local state resets, which can be useful when deliberately resetting a form.
What should I use if my data has no ID?
Use a stable, unique field or assign an ID when the item is created and store it with the data. Do not generate a fresh key during each render; an index is only a reasonable fallback for a genuinely static list.
Interview tip: Start with stable identity, show the todo ID example, and explain how inserting a row can misplace state when indexes are used.
