Akryum / vue-virtual-scroller

⚡️ Blazing fast scrolling for any amount of data
https://vue-virtual-scroller-demo.netlify.app
9.77k stars 916 forks source link

"It seems there are duplicate keys" when scrolling fast #12

Closed gambolputty closed 7 years ago

gambolputty commented 7 years ago

Hello!

I drag the scrollbar with my mouse up and down and everything works fine, no errors. I do the same again very fast, the virtual scroller breaks and I get the following error in my console:

vue.common.js?e881:521 [Vue warn]: It seems there are duplicate keys that is causing an update error. Make sure each v-for item has a unique key. 
warn @ vue.common.js?e881:521
updateChildren @ vue.common.js?e881:4393
patchVnode @ vue.common.js?e881:4450
updateChildren @ vue.common.js?e881:4366
patchVnode @ vue.common.js?e881:4450
updateChildren @ vue.common.js?e881:4366
patchVnode @ vue.common.js?e881:4450
patch @ vue.common.js?e881:4574
Vue._update @ vue.common.js?e881:2642
updateComponent @ vue.common.js?e881:2609
get @ vue.common.js?e881:2934
run @ vue.common.js?e881:3003
flushSchedulerQueue @ vue.common.js?e881:2807
(anonymous) @ vue.common.js?e881:473
nextTickHandler @ vue.common.js?e881:422
vue.common.js?e881:435 TypeError: Cannot read property 'key' of undefined
    at sameVnode (eval at <anonymous> (app.js:723), <anonymous>:4061:11)
    at updateChildren (eval at <anonymous> (app.js:723), <anonymous>:4398:15)
    at patchVnode (eval at <anonymous> (app.js:723), <anonymous>:4450:29)
    at updateChildren (eval at <anonymous> (app.js:723), <anonymous>:4366:9)
    at patchVnode (eval at <anonymous> (app.js:723), <anonymous>:4450:29)
    at updateChildren (eval at <anonymous> (app.js:723), <anonymous>:4366:9)
    at patchVnode (eval at <anonymous> (app.js:723), <anonymous>:4450:29)
    at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:723), <anonymous>:4574:9)
    at VueComponent.Vue._update (eval at <anonymous> (app.js:723), <anonymous>:2642:19)
    at VueComponent.updateComponent (eval at <anonymous> (app.js:723), <anonymous>:2609:10)
logError @ vue.common.js?e881:435

OS: Windows 10 8 GB RAM Browser: Google Chrome 56.0.2924.87

My template:

<virtual-scroller class="scroller" :items="listCompiled" item-height="58" typeField="type" content-tag="table">

    <toolbar :pagination="pagination"
             :groupBy="groupBy"
             :sortBy="sortBy"
             :checkedInvoices="checkedInvoices"
             @update="handleToolbarUpdate"
             slot="before-container"
             ></toolbar>

    <template scope="props">
        <tr v-if="props.item.type === 'groupHeader'" :key="props.itemKey">
            <td class="listItem groupHeader" colspan="5">
                <h3>{{props.item.label}}</h3>
            </td>
        </tr>
        <tr v-if="props.item.type === 'invoice'" class="listItem invoice" :key="props.itemKey" :class="{'active': props.item.checked }">
            <td class="checkBox">
                <el-checkbox v-model="props.item.checked" :label="props.item.id" @change="checkedChange"></el-checkbox>
            </td>
            <td class="wrapClient" v-for="address in addresses" v-if="address.id == props.item.address">
                <span class="client">
                    <span v-if="address.org" class="org">{{address.org}}</span>
                    <span v-if="address.firstname && address.lastname" class="name">{{address.firstname + ' ' + address.lastname}}</span>
                </span>
                <span class="nr">{{props.item.nr}}</span>
            </td>
            <td class="date">{{ props.item.date | moment("D. M. Y") }}</td>
            <td class="dueDate">{{props.item.dueDateComputed}}</td>
            <td class="wrapTotal">
                <span class="total">{{props.item.total | currency}}</span>
                <span :class="'status status-' + props.item.status">{{statusLabel[props.item.status]}}</span>
            </td>
        </tr>
    </template>
</virtual-scroller>

The itemKeys are unique and created like so: new Date().toJSON() + Math.random()

gambolputty commented 7 years ago

Can't reproduce this in the demo, though. I wonder what's wrong with my code :/

gambolputty commented 7 years ago

Sometimes I won't get the "duplicate-keys"-error, but the following one, when dragging the scrollbar up very fast:

vue.common.js?e881:435 DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
    at Object.insertBefore (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:3943:14)
    at updateChildren (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4380:28)
    at patchVnode (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4450:29)
    at updateChildren (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4399:13)
    at patchVnode (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4450:29)
    at updateChildren (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4366:9)
    at patchVnode (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4450:29)
    at updateChildren (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4366:9)
    at patchVnode (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4450:29)
    at VueComponent.patch [as __patch__] (eval at <anonymous> (http://localhost:8080/app.js:723:1), <anonymous>:4574:9)
logError @ vue.common.js?e881:435
gambolputty commented 7 years ago

It seems that this issue is related to non-Trackpad mouse devices and their different scrolling behaviour, since I'm not getting these errors on my Mac.

gambolputty commented 7 years ago

I think I fixed it. I had the same problem with another piece of code, but I guess it applies to this issue, too. The problem was, that I used two v-if-statments after another (inside <template>), when using v-if and v-else-if makes more sense to differentiate between the two type blocks.