livewire icon indicating copy to clipboard operation
livewire copied to clipboard

[Failing Test] Duplicate `wire:key` issues

Open joshhanley opened this issue 4 years ago • 3 comments

This adds a failing tests for the scenario where there are two lists on a page with each element using the same wire:key structure like $loop->index.

If a new element is added to one list with the same wire:key as an element in the other list, when morphdom tries to morph them, it moves the existing one instead of creating a new one.

See screen capture below, where there are two components each displaying the same list. If we add a new user to the child component and refresh the parent, we can see the new user gets moved.

I've added a sleep to the parent component so we can clearly see the user in the child list before the parent refreshes.

I suspect it has to do with Livewire's custom morphdom look ahead.

Hope this helps!

recording (46)

joshhanley avatar Oct 18 '21 10:10 joshhanley

@joshhanley is this a real issue? because I always prefix my keys with the model name or something similar or is it just to illustrate the problem?

nuernbergerA avatar Oct 19 '21 04:10 nuernbergerA

@nuernbergerA yeah that was just to demonstrate the issue and I do the same as you, I probably should have explained it in more detail.

In the screen capture, there are two lists of users, one in the parent component, and another in the nested component, that look like this:

<div>
    @foreach($users as $user)
        <div wire:key="user-{{ $user->id }}">{{ $user->name }}</div>
    @endforeach
</div>

As both sets of users use the same wire:key syntax, it's causing that morphdom error. Normally I would the prefix them differently depending on their context, but in the app I'm currently working on, that is about 3 blade components deep and passing context through to props down each level just for the wire:key doesn't feel right.

I've also noticed a lot of beginner users get tripped up by strange morphdom things like this due to using $loop->index, as that is what is in the documentation.

I'd expect that the wire:keys should only be scoped to an element and only need to be unique within that element, and not cause issues with other matching keys somewhere else in the DOM, same as how VueJS works.

Hopefully, if we can solve this, it will save some pain for new users running into morphdom issues.

joshhanley avatar Oct 19 '21 07:10 joshhanley

Note for ourselves: The solution here is to use Alpine's new "Morph" plugin instead of morphdom - its algo resolves this issue

calebporzio avatar Dec 08 '21 21:12 calebporzio

Closing as this shouldn't be an issue in V3 as keys will be scoped to within the parent element.

joshhanley avatar Nov 17 '22 01:11 joshhanley