When Position Pretends to Be Identity: Understanding key in Vue List Rendering
Using index as a key in Vue can cause state to stick to positions instead of actual data, because Vue uses keys to track identity over time. A proper key ensures components stay aligned with the correct data, even when the list changes.
At first, rendering a list feels simple.
You have data.
You loop through it.
You display it.
<li v-for="(user, index) in users" :key="index">
{{ user.name }}
</li>It works.
Nothing breaks.
Everything looks correct.
And because of that⌠itâs easy to believe this is enough.
But thereâs a quiet assumption hiding underneath this code.
An assumption that only reveals itself when things start to change.
The Illusion of Stability
As long as your list never changes, using the index as a key feels perfectly fine.
Each item has a position:
- first
- second
- third
And each position maps cleanly to a piece of UI.
So it feels natural to say:
âThis item is index 0. Thatâs its identity.â
But that only works in a world where nothing moves.
When the List Starts Shifting
Now imagine something changes.
The first item is removed.
Your list goes from this:
[A, B, C]
to this:
[B, C]
At a glance, this seems straightforward.
You just removed A.
But Vue doesnât see it that way â not when you use index as the key.
What Vue Actually Sees
With :key="index", Vue sees:
Before:
- A â key 0
- B â key 1
- C â key 2
After:
- B â key 0
- C â key 1
From Vueâs perspective, the keys didnât disappear.
They shifted.
So instead of thinking:
âA is gone, B moved, C movedâ
Vue thinks:
âkey 0 is still hereâ
âkey 1 is still hereâ
So it reuses the existing components.
But now something subtle happens.
When Identity Gets Rewritten
The component that used to represent AâŚ
is now reused to represent B.
And the one that used to represent BâŚ
is now reused to represent C.
The structure stays.
But the meaning changes.
And this is where things start to feel⌠off.
State Doesnât Move With Data
If your list is just static text, you might never notice.
But real components often carry internal state.
Inputs. Toggles. Animations. Temporary values.
Now imagine this:
<input v-model="user.name" />You type something into the first input.
Then the list updates.
Suddenly:
- what you typed is still there
- but itâs attached to a different user
The UI looks correct on the surface.
But underneath, the state has been reassigned.
Not because Vue is broken.
But because it followed your instruction.
The Real Meaning of key
At first, itâs tempting to think:
âkey helps Vue update efficientlyâ
But thatâs not the full story.
A better way to see it is:
key tells Vue what is the same thing over time.
Not the same position.
Not the same slot in a list.
The same entity.
Position vs Identity
When you use the index as the key, youâre saying:
âIdentity is defined by positionâ
But in most real applications, thatâs not true.
Users donât become someone else just because they moved up the list.
Items donât lose their identity when something is inserted before them.
So when position changes, but identity is tied to positionâŚ
you get a mismatch.
And that mismatch is where bugs live.
When Index Actually Works
There are cases where using index is completely fine.
When:
- the list never changes
- items are never reordered
- nothing is inserted in the middle
- components donât hold internal state
In those cases, position is stable.
And if position is stable, it can safely act as identity.
But those cases are rarer than they seem.
A Small Detail That Changes Everything
Using a proper key, like an ID:
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>Changes how Vue understands your UI.
Now it can say:
- this item stayed
- this one moved
- this one is new
- this one is gone
Not based on position.
But based on identity.
The Subtle Bug You Donât See
The most dangerous part of using index as a key is that it often looks fine.
The UI renders.
The data appears correct.
Nothing crashes.
But under the surface, state is drifting.
Quietly.
Until one day, something feels off.
An input shows the wrong value.
An animation behaves strangely.
And itâs hard to trace back why.
A Shift in Perspective
At first, key feels like a technical requirement.
Something you add because Vue tells you to.
But itâs actually something deeper.
It forces you to answer a question:
âWhat makes this item the same⌠even when everything around it changes?â
And once you start thinking that wayâŚ
you stop writing lists based on position.
And start thinking in terms of identity.
And that small shift changes everything.