Why are keys critical in v-for? What exactly breaks when you use array index as a key?

LowIntermediateVue
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

Explain why keys are required in v-for, how Vue uses them during virtual DOM diffing, and what subtle but serious bugs happen when you use array index as a key (state reuse, wrong DOM nodes, broken animations, and input mix-ups).

Answer

Overview

Keys are how Vue identifies which virtual DOM node corresponds to which real DOM node across renders. If keys are stable and unique, Vue can correctly reuse, move, or destroy elements. If keys are wrong (or you use the array index), Vue will reuse the wrong DOM nodes, causing bugs like inputs swapping values, components keeping the wrong state, and animations glitching.

1. What Vue actually does when a list changes

When a list rendered with v-for changes, Vue does not recreate the whole DOM. It diffs the old list and the new list and tries to match items using their key.

With good keys

With bad keys (or index)

Vue moves the correct DOM nodes

Vue reuses DOM nodes for the wrong items

Component state stays with the right item

Component state gets attached to the wrong item

Minimal DOM operations

Unpredictable patches and visual glitches

How keys affect Vue’s diffing behavior

2. The correct pattern

Always use a stable, unique ID that represents the identity of the item, not its position.

HTML
<li v-for="todo in todos" :key="todo.id">
  <TodoItem :todo="todo" />
</li>
                  

3. The tempting but dangerous pattern

Using the array index looks fine… until the list changes.

HTML
<!-- ❌ Bad -->
<li v-for="(todo, index) in todos" :key="index">
  <TodoItem :todo="todo" />
</li>
                  

4. What exactly breaks when you use index as key?

Operation

What you expect

What actually happens with index key

Insert item at top

New DOM node is created at top

Vue reuses every existing DOM node and just shifts data

Remove an item

That item’s DOM and component state are destroyed

A different item’s DOM gets reused and keeps stale state

Reorder list (sort, drag & drop)

Items move with their DOM and state

DOM stays in place, only data changes → state mismatch

Edit inputs in a list

Each input keeps its own value

Values appear to jump to other rows

Concrete bugs caused by index as key

5. The classic horror demo: inputs swapping values

HTML
<div v-for="(user, i) in users" :key="i">
  <input v-model="user.name" />
</div>

<button @click="users.unshift({ name: '' })">Add to top</button>
                  

When you click the button, the text you typed appears to move to a different row. Vue reused DOM nodes by position, not by identity.

6. Why Vue can’t magically fix this

Vue has no way to know whether an item at index 0 is “the same logical item as before” or a different one. The key is the only identity signal you give to the diffing algorithm.

7. When is index as key actually safe?

Almost never — but technically OK if all of these are true:

      • The list is static (no insert/remove/reorder).
      • The list items have no internal state (no inputs, no components with state).
      • You will never filter or sort it.
In practice: for real apps, just don’t.

8. How this relates to performance

Good keys don’t just fix bugs — they also make updates faster because Vue can move nodes instead of destroying and recreating them.

Mental model: keys tell Vue “who is who”. If you lie about identity (using index), Vue will faithfully do the wrong thing — very efficiently.

Summary

Summary

      • Keys define the identity of list items for Vue’s diffing algorithm.
      • Using index as key ties identity to position, not to the actual item.
      • This causes state to stick to the wrong DOM nodes: broken inputs, wrong component state, glitchy animations.
      • Always use a stable, unique ID from the data itself.

Similar questions
Guides
31 / 34