Why Your List Re-renders Are Slow: Mastering React Keys
Using array index as a React key causes unnecessary re-renders and state loss. Learn how stable, unique keys enable efficient reconciliation.
15 Nov 2025, 14:37 UTC

The Problem: A List That Forgets Everything
You've built a todo list. Items reorder smoothly. Then you add a filter. Suddenly, input fields lose focus, checkboxes reset, and performance stutters. The culprit isn't React's speed—it's your keys.
React's Reconciliation: How Keys Guide the Diff
React's fiber-based reconciliation performs a depth-first traversal, comparing element types and props. When it encounters a list, it uses keys to track which items changed, were added, or removed. Without stable keys, React can't efficiently reuse existing DOM nodes, triggering full teardowns and recreations.
Elements with different types always trigger complete DOM node replacement. But even with matching types, unstable keys force React to discard and recreate components, resetting their internal state.
The Index-as-Key Anti-Pattern
Using array index as a key seems logical—it's always unique within the array. But when you reorder, insert, or delete items, the index changes for every subsequent element. React sees this as every item being removed and a new one added, destroying component state and causing unnecessary work.
Consider a list of three items keyed by index: [0, 1, 2]. Delete the first item. React now sees keys [0, 1] where the old item with key 0 is gone and a new item occupies that position. Even though the content might be similar, React discards the old component instance entirely.
A Practical Example: Todo List with Stable IDs
// Bad: Index-based keys
{items.map((item, index) => (
<TodoItem key={index} item={item} />
))}
Instead, use stable unique identifiers:
// Good: ID-based keys
{items.map(item => (
<TodoItem key={item.id} item={item} />
))}
When reordering items, React can efficiently swap DOM positions without destroying component instances. State persists, and performance remains optimal.
Trade-offs and Limitations
Stable keys require a unique identifier in your data model. If your items lack natural IDs, generate them using libraries like nanoid or maintain a separate ID counter. However, keys must be stable across renders—generating new IDs each render defeats the purpose.
React 18's concurrent features can defer reconciliation, but key stability remains essential. The algorithm still needs predictable identifiers to make correct update decisions.
Verification and Next Steps
Test your implementation with React DevTools. Add items, remove them, and reorder. Watch the component tree—stable keys should preserve existing instances rather than creating new ones. If you see unexpected unmounting, examine your key strategy.
For dynamic lists, always use stable, unique keys derived from your data. This single change eliminates a common performance bottleneck and prevents subtle state-related bugs.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.