When rendering lists with .map(), each item needs a unique key prop so React's reconciliation algorithm can efficiently track which items changed, were added, or removed between renders.
Keys give React a stable identity for list items, enabling efficient reconciliation — React matches elements by key, not position.
Using array index as key causes state bugs when items are reordered, inserted, or removed — component state attaches to the wrong items.
Database IDs are ideal. Keys must be unique among siblings and stable across renders. Never use Math.random() at render time.
React consumes key internally — it's not available as props.key in the child component. Pass the ID as a separate prop if needed.
Proper keys let React reuse DOM nodes on reorder/insert. Without keys, inserting one item can cause the entire list to re-render.
Rendering dynamic lists is one of the most common tasks in React. The key prop is React's mechanism for efficiently tracking list items during re-renders — misusing it causes subtle bugs and performance problems.
Use .map() to transform an array of data into an array of JSX elements: items.map(item => <ListItem key={item.id} data={item} />). Each element in the array must have a key prop — React uses it to identify elements across renders.
When a list changes (items added, removed, or reordered), React needs to figure out which DOM nodes to create, delete, or move. Without keys, React compares elements by position — if you insert an item at the beginning, React thinks every item changed (position 0 is different, position 1 is different, etc.) and re-renders the entire list.
With stable keys, React matches elements by key value. If you insert an item at the beginning, React sees that all existing keys still match — it only creates one new DOM node and shifts the others. This is dramatically more efficient for large lists.
During reconciliation, React compares the old and new element trees:
This key-based matching is what enables efficient list updates.
Using array index as key (items.map((item, index) => <Item key={index} />)) causes bugs when the list is reordered, items are inserted at the beginning, or items are removed from the middle. React associates component state with the key — if you remove item at index 2, the item at index 3 inherits index 2's state (because its key is now 2). This causes input values, animations, and focus to shift to wrong items.
Index as key is only safe when the list is static (never reordered, never filtered) and items have no state.
crypto.randomUUID() generated once at data creation time (not at render time)Math.random() — generates a new key every render, so React destroys and recreates every item. Terrible for performance.Keys tell React which items in a list correspond to which DOM nodes across renders. Without stable keys, React falls back to positional comparison which causes unnecessary re-renders and state bugs. Use database IDs or stable unique values — never use index for dynamic lists or Math.random() for any list.
Fun Fact
The key prop is one of the few React props with special behavior — it's consumed by React internally and never appears in props.key. The other special prop is ref. Both are 'reserved' and serve React's internal mechanics rather than the component's logic.