42

I'm building a clone of HackerNews and am getting the following error:

vue.esm.js?efeb:591 [Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

found in

---> <Single> at src/components/Single.vue
       <App> at src/App.vue
         <Root>

The error seems to be coming from Single.vue but I can't work what it is? The template is as follows:

<template>
    <div class="container">
        <h2>{{ story.title }}</h2>
        <p>Score: {{ story.score }}</p>
        <p>{{ story.url }}</p>
        <div v-for="comment in comments" :key="comment">
          <div class="comment-wrap">
                <div class="comment-block">
                    <p class="comment-text">{{ comment.text }}</p>
                    <div class="bottom-comment">
                        <div class="comment-author">{{ comment.by }}</div>
                        <div class="comment-date">{{ comment.time }}</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

If anyone out there can help, that would be great!?

Drostan
  • 1,809
  • 3
  • 16
  • 22

7 Answers7

77

Other answers work, but the following is also worth a try:

<div v-for="(comment, idx) in comments" :key="idx">
  <!-- ... -->
</div>
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
silvan
  • 1,103
  • 1
  • 8
  • 6
34

The warning sources from <div v-for="comment in comments" :key="comment">, where the object comment is used as a key for v-for. The meaning of the warning is quite literal, don't use Object as key.

Use unique primitive value as key, maybe something like comment.id or ${comment.time}${comment.by}

William Chong
  • 2,107
  • 13
  • 24
22

You can simply avoid the use of :key in your v-for.

...
<div v-for="comment in comments">
...

As vuejs documentation said:

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.

tony19
  • 125,647
  • 18
  • 229
  • 307
jotade
  • 438
  • 2
  • 5
  • 18
    This is working but it result whit IDE warning "Element in iteration expect to have v-bind:key derictives" – Vasil Valchev May 17 '19 at 14:06
  • 1
    It is recommended to follow the guidelines. Why you not use a computed propety to return a comment in string format? :key="getComents(comment)". That works. – Nuno Ribeiro Dec 26 '19 at 14:30
9

Below is an example of what works for me. Hope that helps

enter image description here

accimeesterlin
  • 4,528
  • 2
  • 25
  • 18
  • 4
    Not recommended as explained here https://stackoverflow.com/questions/44531510/why-not-always-use-the-index-as-the-key-in-a-vue-js-for-loop – asus Nov 13 '19 at 19:01
8

Use unique primitive value as key, It is recommended to provide a key attribute with v-for whenever possible.

like :key="design.uniqueId"

<li v-for="design in designs" :key="design.id">
    <!-- code -->
</li>

<li v-for="loop in loops" :key="loop.id">
    <!-- code -->
</li>

Such as Vue.js Documentation

tony19
  • 125,647
  • 18
  • 229
  • 307
Vishal Vaghasiya
  • 1,857
  • 2
  • 14
  • 21
2

as per vue js Maintaining State Doc it says your id is find multiple times

That means your code should look like this

div v-for="comment in comments" :key="comment.id">

insted of

div v-for="comment in comments" :key="comment">

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

tony19
  • 125,647
  • 18
  • 229
  • 307
TarangP
  • 2,711
  • 5
  • 20
  • 41
0

Maybe you are using an Object type as the key, if it can be converted into a unique string, use the string instead of the instance by calling such as toString.

I had same issue when I used mongoose.Types.ObjectId() as the key, after I changed to mongoose.Types.ObjectId().toHexString() the warning disappear.

Necowood
  • 1
  • 2