Simple clarification of when using :key with v-for is appropriate and why

I don’t understand the documentation’s description of when using a :key with v-for is needed to avoid issues. Can someone give a simple example of when using :key vs not using :key would be appropriate as well as a simple explanation (maybe what is happening behind the scenes).

Again the documentation’s language is going over my head a bit.

Thanks!

2 Likes

You should always use it if you do a v-for on a component, or if you’re using transitions. Otherwise you don’t need it.

For example, if you do this:

<div v-if="toggle">Hello</div>
<div v-else>Goodbye</div>

Then when toggle is changed, instead of deleting the div and creating a new one, Vue will just replace “Hello” with “Goodbye”. This is faster, but if you want enter/leave animations, they won’t trigger. So you’d have to do:

<transition>
  <div v-if="toggle" key="1">Hello</div>
  <div v-else key="2">Goodbye</div>
</transition>
2 Likes

I’m not sure if that answers my questions…I am referring to this section of the vue guide:


key
When Vue is updating a list of elements rendered with v-for, by default it uses an “in-place patch” strategy. If the order of the data items has changed, instead of moving the DOM elements to match the order of the items, Vue will patch each element in-place and make sure it reflects what should be rendered at that particular index. This is similar to the behavior of track-by="$index" in Vue 1.x.

This default mode is efficient, but only suitable when your list render output does not rely on child component state or temporary DOM state (e.g. form input values).

To give Vue a hint so that it can track each node’s identity, and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item. An ideal value for key would be the unique id of each item. This special attribute is a rough equivalent to track-by in 1.x, but it works like an attribute, so you need to use v-bind to bind it to dynamic values (using shorthand here):

   _<div v-for="item in items" :key="item.id">
   _  <!-- content -->
   _</div>

It is recommended to provide a key with v-for whenever possible, unless the iterated DOM content is simple, or you are intentionally relying on the default behavior for performance gains.

Since it’s a generic mechanism for Vue to identify nodes, the key also has other uses that are not specifically tied to v-for, as we will see later in the guide.


What you quoted from the documentation is exact @Herteby’s answer. Which aspect you don’t understand?

When:

It is recommended to provide a key with v-for whenever possible

Why:

To give Vue a hint so that it can track each node’s identity

I think I understand the question so I’ll take a stab at it, though I’m not fully aware of the internal details.

Lets say you have one of these todo lists that folk are clearly making millions with these days

tasks: [
    {
        description: "dry"
    },{
        description: "wash"
    }
]

You render the task’s with a v-for and bind them to a template
which uses the task description for a label

<li v-for="task in tasks">
    {{ task.description }}
</li>

Then an advanced algorithm determines that the wash task should be moved before the dry task in order to make for a happier puppy, vue will keep the elements on the page in the same order and just change the text of those elements, the first and third tags, which is very efficient, especially in simple cases with a lot of data like lists of simple form items.

But say you have more complex objects and computed properties in your template

tasks: [{
    id: task1,
    pet: {
            id: pet1
            type: dog,
            name: fido,
         }
    description: "wash"
},
    id: task2,
    pet: {
          id: pet1
          type: dog,
          name: fido,
       }
    description: "dry"
}]

<li v-for="task in tasks" :key="task.id">
    {{ task.description + task.pet.name }}
</li>

Now vue wants to have those id’s so it can determine the dependencies and determine what to recompute and what to redraw,

The keys are also important because different browsers use different ways to keep track of the order and display of certain object arrays, so In the end without a key, it just becomes easy for confusing mistakes or edge case errors to occur.

1 Like

@Cortrah I’m sorry to say this but you are totally on the wrong track here.

The complexity of the data doesn’t matter, it’s the complexity of the interactions and changes to the nodes of the for loop.

No.Browsers and their differences don’t play any role here, the browser itself never sees the key, it’s not an html attribute, it’s only used by Vue internally in its virtual DOM handling algorithms.

To answer @brandonwoz question:

Whenever you manipulate a list in a way that results in a change of indexes, you have to use a key so Vue can update the DOM correctly after these changes.

These manipulations include:

  • adding an item to an array, in any place other than the end of the array
  • removing an item from an array, from any place other than the end of the array
  • re-ordering (sorting) the array in any way.

If your list is never changed during the lifetime of your component, or you only append items, you don’t need a key.

Since in real life, you will often find your self switching from the “not needing a key” bucket to the “needing a key” bucket as requirements change, we recommend to make it a habbit and always key all your for loops.

If you try and keep track where you need one and where you don’t you will inevitably end up with bugs because you forgot / misinterpreted something.

7 Likes

Np Linus. Thanks for the clarification then!

Thanks for everyones replies. It makes sense now. The part about appending at the end vs mutating something in the middle, helped make the concept a bit more intuitive now. Thanks again!

1 Like

This was helpful, I have been looking to make my grid more user friendly so I can order chronologically and filter etc. But not seeing the key generated in the <li> tag made me think I’d misused it. But it seems that not seeing it is correct?

Could the key be the index? Or is that dangerous? I have array that items can shift up or down and be removed. My main problem is I dont have an unique key always from the data itself. Would it be okay to add Math.random() to ensure the key is unique. I guess Im asking could I simply make the a key guid() number or should it be something more readable.

Im guessing since its simply for the vue engine, it does not need to be, could someone please help my understanding?

Thanks!

as the index will change over time, it’s not usable as a key that identifies the item.

You can usually create unique keys based on something from your data + the index.

While this will work, the downside is it will always create unique keys rather than reusing them so performance wise it’s not optimal. The best option would be to create unique keys and store them to be checked against. This topic discusses it and provides a solution: Array index as v-for key results in problems when removing items from the list