A lot of users get upset when the linter yells at them for not providing a key when it doesn't create a real problem and Vue itself doesn't complain. The real intent with this rule is to maintain object constancy to avoid:
data properties being reset, lifecycle methods being re-run unnecessarily)input, select, etc (e.g. value being lost if not passed as a prop)<transition> or <transition-group> elements. To make everyone happy, I'm wondering if we may want to rename require-v-for-key to something like require-v-for-key-stateful-elements, then change its behavior so that it only gives a warning on:
v-html<transition> or <transition-group>.I'd like to get some other people weighing in on this before making the change, as there may be other cases I'm not considering.
I'm adding some specific messages and examples for each case here, to make building the rule easier.
key with v-for on componentMissing
keyattribute on a component usingv-for. Akeyis required to help Vue uniquely identify each component in the list, so that it can avoid recreating components and destroying their local state.
<my-component v-for="n in 2"/>
<MyComponent v-for="n in 2"/>
key with v-for on stateful elementMissing
keyattribute on a stateful element (e.g.input,select, etc) usingv-for. Akeyis required to help Vue uniquely identify each element in the list, so that it can avoid recreating these and destroying their state.
<input v-for="n in 2">
<select v-for="n in 2">
...
</select>
key with v-for on element using v-htmlMissing
keyattribute on an usingv-forandv-html. Akeyis required to help Vue uniquely identify each element in the list, so that it can avoid recreating these and potentially destroying the local state of any stateful elements (e.g.input,select, etc) that they render.
<div v-for="n in 2" v-html="n"/>
<span v-for="n in 2" v-html="'<p>hi</p>'"/>
key with v-for on element with stateful contentMissing
keyattribute on an element with stateful content. Akeyis required to help Vue uniquely identify each element in the list, so that it can avoid recreating its content and potentially destroying the local state of any components or stateful elements (e.g.input,select, etc) they contain.
<div v-for="n in 2">
<my-component/>
</div>
<div v-for="n in 2">
<input>
</div>
<div v-for="n in 2">
<div v-html="n"/>
</div>
key with v-forThe
keyattribute on elements usingv-formust usev-bindto reference a property defined by thev-for, so that the value of eachkeywill be unique.
<MyComponent v-for="n in 2" key="foo"/>
<!-- Does not use any properties defined in `v-for` -->
<MyComponent v-for="n in 2" v-bind:key="foo"/>
<!-- Does not use any properties defined in `v-for` -->
<MyComponent v-for="n in 2" :key="foo"/>
This would require us to be able to access the names of any properties (e.g. n in the examples above) and ensure that it is used within the value of the key, if the key if using v-bind.
key with v-for on transitioned elementMissing
keyattribute on an element with a parent of<transition>or<transition-group>. Akeyis required to help Vue uniquely identify each element in the list, so that it can maintain visual object constancy.
<transition>
<div v-for="n in 2"/>
</transition>
<transition-group>
<div v-for="n in 2"/>
</transition-group>
This one isn't _really_ related to v-for specifically, as it also applies to elements with v-if/v-else-if/v-else that share a tag name. So maybe it should be in a separate rule?
This is how all proposal should look like! Really good piece of work @chrisvfritz 馃
I agree with everything, but one case: Non-unique key with v-for - I mean it's all good, but I'm thinking whether this single case shouldn't be in a separate rule, as it's kind of independent from what's being proposed in other examples, and one rule should do one thing in eslint.
So the way I see it is by having two separate rules:
require-v-for-key (we need to update current one)unique-v-for-key (new)We should also take cases with <template> and <slot> into consideration, am I right?
<template v-for="n in 2">
<my-component/> <!-- missing key -->
</template>
<template v-for="n in 2">
<input> <!-- missing key -->
</template>
<template v-for="n in 2">
<div v-html="n" /> <!-- missing key -->
</template>
This is how all proposal should look like! Really good piece of work @chrisvfritz 馃
:blush: 馃檲
I agree with everything, but one case: Non-unique key with v-for - I mean it's all good, but I'm thinking whether this single case shouldn't be in a separate rule, as it's kind of independent from what's being proposed in other examples, and one rule should do one thing in eslint.
That sounds good to me. 馃檪
We should also take cases with and
into consideration, am I right?
Yes, absolutely!
Hello people, any progress on this? I could probably take a shot at it, with a bit of guidance from a maintainer.
Also, as a suggestion, can we also add a :key="index" check to all the scenarios identified by @chrisvfritz ? In other words, emit a warning if either there's no key, or if key is set to the v-for index (of which I've encountered lots of cases while helping people on the Vue official chat). I'm not sure if this should be part of the same rule (although, implementation wise, the check and the warning message would be very similar), any thoughts?
@michalsnik @chrisvfritz Ping?
Most helpful comment
I'm adding some specific messages and examples for each case here, to make building the rule easier.
Missing
keywithv-foron componentMessage
Examples
Missing
keywithv-foron stateful elementMessage
Examples
Missing
keywithv-foron element usingv-htmlMessage
Examples
Missing
keywithv-foron element with stateful contentMessage
Examples
Non-unique
keywithv-forMessage
Examples
Notes
This would require us to be able to access the names of any properties (e.g.
nin the examples above) and ensure that it is used within the value of thekey, if thekeyif usingv-bind.Missing
keywithv-foron transitioned elementMessage
Examples
Notes
This one isn't _really_ related to
v-forspecifically, as it also applies to elements withv-if/v-else-if/v-elsethat share a tag name. So maybe it should be in a separate rule?