vuetifyjs / vuetify

🐉 Vue Component Framework
https://vuetifyjs.com
MIT License
39.83k stars 6.96k forks source link

[Bug Report][3.7.2] VAutocomplete: "Multiple nodes with the same ID" error when backspacing after "no-data" state #20516

Open panypticon opened 1 month ago

panypticon commented 1 month ago

Environment

Vuetify Version: 3.7.2 Last working version: 3.7.1 Vue Version: 3.4.27 Browsers: Opera 113.0.0.0 OS: Mac OS 10.15.7

Steps to reproduce

Type a random string until "no data available" appears, then backspace until field is empty

Expected Behavior

No error in console

Actual Behavior

"Multiple nodes with the same ID" error

Reproduction Link

https://play.vuetifyjs.com/#...

Other comments

Caused by https://github.com/vuetifyjs/vuetify/commit/970f827828b2e488ad5bb2e8f1363fd38c5a6102#diff-9e9ae93c534ad2f413745ba1b6de47726b919dcb966ea267faaa99f75b337a96R219

ottopaulsen commented 2 weeks ago

There is something wrong in version 3.7.2 causing this error message. I am getting the same error in a very strange place.

[Vue warn]: Vuetify error: Multiple nodes with the same ID
    /campaigns
    /campaigns 
  at <VListItem to= {name: 'campaigns'} exact=false class="menuItem"  ... > 
  at <PortalMenuItem key=1 title="Campaigns" to= {name: 'campaigns'}name: "campaigns"[[Prototype]]: Object  ... > 
  at <VListChildren items= [] returnObject=false > 

The error is coming from where I create the navigation menu, but it is reported on a line of code that has nothing to do with this.

In version 3.7.1 I am getting no error.

PawelJarosiewicz commented 2 weeks ago

I have the same error with v-combobox on version 3.7.2. After switching to version 3.7.1 there is no error.

My combo: <v-combobox v-model="startReportForm.productType" auto-select-first="exact" autofocus class="mb-4" color="secondary" :hint="startReportForm.productType?.description" item-title="name" :items="productTypes" label="Rodzaj produktu" persistent-hint return-object variant="outlined"

Steps to reproduce:

NathanAP commented 2 weeks ago

I'm also getting this:

<v-autocomplete>
  <template #item="{ item }">
    <v-list-item
      :id="item.raw.key"
      :to="item.raw.to"
      @click="selectItem"
    >
     ...
  </template>
</v-autocomplete>

I tried to add the id and see if it changes anything, but had no luck.

striderwhite commented 1 week ago

Getting this too but with list items

lubuger commented 4 days ago

Issue persists with vuetify 3.7.3 and vue 3.5.12

orjan commented 4 days ago

@J-Sek would you mind having a look at this issue? We solved one issue but introduced a new one, do you have an idea how to approach a fix for the problem above?

J-Sek commented 4 days ago

We solved one issue but introduced a new one, do you have an idea how to approach a fix for the problem above?

It looks like list items are keyed by index instead of item.value and it causes issues with unreliable calls on onBeforeUnmount. While it can be easily fixed, it uncovered another issue – this time warning is triggered with typing the first letter. To force correct list of registered nodes we could clear filtered items and reapply them in nextTick, but it makes filter.ts coupled with rendering logic and also is not unit-test friendly :/ Not sure if the core team will pass this.

Asko-Dev commented 3 days ago

+1 Also getting this with <v-list> and <v-list-items> children, on the items that have the same to route.

J-Sek commented 2 days ago

+1 Also getting this with <v-list> and <v-list-items> children, on the items that have the same to route.

@Asko-Dev, could you share code with playground? I would check if my current PR covers this or not.

orjan commented 2 days ago

+1 Also getting this with <v-list> and <v-list-items> children, on the items that have the same to route.

@Asko-Dev, could you share code with playground? I would check if my current PR covers this or not.

Is there a playground that includes vue-router? Otherwise I can try to setup a new repository.

KaelWD commented 2 days ago

The dev environment in this repo has it: https://vuetifyjs.com/en/getting-started/contributing/#local-development

J-Sek commented 2 days ago

Or fork this Stackblitz project

Asko-Dev commented 2 days ago

I hope I did this right, first time using it. Just let it all load and it should show the warning. Thank you

https://stackblitz.com/edit/vuetify-base-qjaut5?file=pages%2Findex.vue

J-Sek commented 2 days ago

Same with href (example). I think it needs separate issue and it would be great to hear compelling reason to suppress the warning in such scenario as it looks like most devs would prefer it to avoid duplicated links.

orjan commented 2 days ago

Same with href (example). I think it needs separate issue and it would be great to hear compelling reason to suppress the warning in such scenario as it looks like most devs would prefer it to avoid duplicated links.

In my case it was a wrongly keyed v-for causing the duplicated links warning. I'll guess it's pretty rare case with the same link in the same list?

Asko-Dev commented 2 days ago

Same with href (example). I think it needs separate issue and it would be great to hear compelling reason to suppress the warning in such scenario as it looks like most devs would prefer it to avoid duplicated links.

In my case it was a wrongly keyed v-for causing the duplicated links warning. I'll guess it's pretty rare case with the same link in the same list?

in my project the v-list-item is used in a dropdown menu of a user, some items though are locked if you don't have Premium and therefore lead to a Premium purchase page when clicked on ...which I don't think could be such rare occurrence. But I am sure a workaround with a simple click event would suffice, though it surely would be nicer to just be able to use it especially if different keys are assigned

orjan commented 2 days ago

in my project the v-list-item is used in a dropdown menu of a user, some items though are locked if you don't have Premium and therefore lead to a Premium purchase page when clicked on ...which I don't think could be such rare occurrence.

I think that this makes sense and is a valid use case.

From an api point of view it's also a little bit problematic causing a runtime side effect, by just adding another v-list-item element?

J-Sek commented 1 day ago

But I am sure a workaround with a simple click event would suffice, though it surely would be nicer to just be able to use it especially if different keys are assigned

Even easier would be to set value prop (e.g. :value="item" in this example) as it will take precedence when computing nested item ID.

// VListItem.tsx sources, line 118
const id = computed(() => props.value === undefined ? link.href.value : props.value)
Asko-Dev commented 1 day ago

But I am sure a workaround with a simple click event would suffice, though it surely would be nicer to just be able to use it especially if different keys are assigned

Even easier would be to set value prop (e.g. :value="item" in this example) as it will take precedence when computing nested item ID.

// VListItem.tsx
const id = computed(() => props.value === undefined ? link.href.value : props.value)

much easier ☺️ awesome, thank you

c-malecki commented 17 hours ago

Just to add to this, I'm experiencing the same warning/error currently in a completely different case than I see described here. Sorry, it's a bit complex. It's also only for a single selection VAutocomplete (not multiple)

I have a VAutocomplete that I've built some async stuff on top of.

When typing in the autocomplete, a request is debounced to send the search term to the backend, so only one request is sent. When the request resolves, the items for the autocomplete list are updated. In my case, it's two arrays being merged from the response body.

One is the "cached" selection (items selected on the client side) and the other is the new selection list (query specifically ensures the selection does not include anything from "cached."

So the items provided to the VAutocomplete are entirely unique, in both names (title) and IDs (value) as confirmed by the results of the response body.

After making a selection and the model value updates, a request is sent to sync the cached values and update the selection again.

This is when I'm getting that warning/error.

AutocompleteAsync.vue:161 [Vue warn]: Vuetify error: Multiple nodes with the same ID
    1
    1 

I'm also ensuring that only request is sent after making a selection, even though the search text is reset. It will consistently happen for the same item/ids depending on the search and selection, but different items/ids from different searches even though the response from the sync request is basically the same "default" list every time.

So in my case, it seems to happen when the items are updated after making a selection. The item causing the duplicate error isn't present in the list when the selection is made, so it's not like the list pre-selection happens to include the same item causing the error after the list is updated post-selection.

To try to illustrate the flow of actions One search and selection:

AutocompleteAsync.vue:268 search text watcher... search text:  m is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  me is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  met is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  meta is syncing values:  false
AutocompleteAsync.vue:204 handle search debounce... search text:  meta is syncing values:  false
AutocompleteAsync.vue:259 model value watcher... search text:   is syncing values:  true
AutocompleteAsync.vue:166 [Vue warn]: Vuetify error: Multiple nodes with the same ID
    569807
    569807 

Another search and selection:

AutocompleteAsync.vue:268 search text watcher... search text:  a is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  ar is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  arg is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argo is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argos is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argosi is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argosig is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argosigh is syncing values:  false
AutocompleteAsync.vue:268 search text watcher... search text:  argosight is syncing values:  false
AutocompleteAsync.vue:204 handle search debounce... search text:  argosight is syncing values:  false
AutocompleteAsync.vue:259 model value watcher... search text:   is syncing values:  true
AutocompleteAsync.vue:166 [Vue warn]: Vuetify error: Multiple nodes with the same ID
    1
    1 

search text watcher fires from typing but request isn't sent until handle search debounce is syncing values is false until the model values watcher fires selection is made and is syncing values is set to true in model value watcher is syncing values = true prevents the search request from firing in search text watcher when the input text is reset from the selection event request resolves and updates the items provided to the VAutocomplete error occurs

In both of these examples, the items returned by the request are actually the same lists (they happen to be the first 50 results of the dataset when the search text isn't used in the query being executed in the backend), but it's a different item in that list that is causing the error depending on the search and selection made, but it will consistently be the same two when I do the same exact search and selection 569807 and 1

Seems like something strange happening in assigning the nodes for the list render, even when there are no duplicate values of any sort in the items being provided

Addendum: no-filter is also set to true, so that the list isn't filtered by vuetify at the same time as typing in the search input

J-Sek commented 17 hours ago

Your gut feeling is correct. The warning depends on nested lists resolution that is currently closely related to the order in which Vue decides to render VListItems - which is not "clear all » render all" but rather an algorithm going through vnodes applying changes in the most cost-efficient way.

I believe your issue would be resolved by both solutions suggested in the currently open PR. It's just a matter of Kael's decision. If you could provide minimal repro on the Playground I could verify it even earlier.

c-malecki commented 17 hours ago

Your gut feeling is correct. The warning depends on nested lists resolution that is currently closely related to the order in which Vue decides to render VListItems - which is not "clear all » render all" but rather an algorithm going through vnodes applying changes in the most cost-efficient way.

I believe your issue would be resolved by both solutions suggested in the currently open PR. It's just a matter of Kael's decision. If you could provide minimal repro on the Playground I could verify it even earlier.

Thanks for the speedy reply and confirmation. I'll try to a Playground up and respond but work comes first unfortunately. I've already spent too much time reworking our asnyc autocomplete -_- (which is how I discovered this)