5 min read
0%

Keys and List Re-render Behavior

Back to Blog
Keys and List Re-render Behavior

Keys and List Re-render Behavior

Keys are React’s hint for matching elements across renders. Getting them wrong causes missed updates, incorrect state, and performance regressions.

Why Keys Exist

Without keys, React reconciles lists by position. If the list changes order or items are inserted, React patches existing DOM nodes rather than moving them:

// Before: [A, B, C]
// After:  [X, A, B, C]  (prepend X)
// Without keys: React patches all 4 positions — 4 DOM updates
// With keys: React inserts X, moves A/B/C — 1 DOM insertion

Key Rules

Must be stable — same item must have the same key across renders:

// Bad: key changes every render
{items.map(item => <Item key={Math.random()} data={item} />)}

Must be unique among siblings — not globally:

// Fine: key 'id-1' appears in both lists, different parent siblings
<ul>{listA.map(i => <li key={i.id}>{i.name}</li>)}</ul>
<ul>{listB.map(i => <li key={i.id}>{i.name}</li>)}</ul>

Must be a string or number — objects as keys do not work.

Index as Key

Index keys are acceptable for static lists that never reorder or filter. They cause bugs when the list is dynamic:

// Bug: uncontrolled inputs retain old values after prepend
{items.map((item, i) => (
  <input key={i} defaultValue={item.name} />
))}

If you prepend an item, the first input gets key 0 — the same key the old first item had. React reuses the DOM node, so the defaultValue never updates.

Use index keys only when the list is static and items have no state.

Key-Based Remounting

Change a key to force a full remount — fresh state, fresh effects:

<UserProfile key={userId} userId={userId} />

When userId changes, React sees a different key at that position and fully unmounts/remounts UserProfile. This is the cleanest way to reset a component’s internal state when a prop changes.

Fragment Keys

Keys work on fragments, but the shorthand <>...</> does not support them — use <React.Fragment key={...}>:

{items.map(item => (
  <React.Fragment key={item.id}>
    <dt>{item.term}</dt>
    <dd>{item.definition}</dd>
  </React.Fragment>
))}

Performance Impact

Wrong keys cause unnecessary unmount/remount cycles — slower than prop patches. Correct keys let React reuse DOM nodes when list order changes — meaningful win for large lists.


Canvas is not supported in your browser