adityar15's avatar

What is the difference between :wire:key and :key?

Hi,

I am finding it a bit weird in the Livewire component syntax.

When I used

@foreach($users as $user)
<livewire:user :key="now()->timestamp.$user->id" />
@endforeach

I got an error like cannot read property fingerprint of null.

After some research, I found out the correct syntax is

@foreach($users as $user)
<livewire:user :wire:key="now()->timestamp.$user->id" />
@endforeach

The problem was sorted but somehow after few days, the web app worked fine on the live server but on the dev server it gave the same error cannot read the property fingerprint of null.

When I change it back to

@foreach($users as $user)
<livewire:user :key="now()->timestamp.$user->id" />
@endforeach

it worked fine.

Can anyone please tell me the difference between :key and :wire:key ?

0 likes
8 replies
Logendher Gunasekaran's avatar

Dom Diffing Issues

The most common issues encountered by Livewire users has to do with Livewire's DOM diffing/patching system. This is the system that selectively updates elements that have been changed, added, or removed after every component update.

For the most part, this system is reliable, but there are certain cases where Livewire is unable to properly track changes. When this happens, hopefully, a helpful error will be thrown and you can debug with the following guide.

Symptoms:

An input element loses focus An element or group of elements dissapears suddenly A previously interactive element stops responding to user input A loading indicator mis-fires A user action no longer functions

Cures:

Ensure your component has a single-level root element

Add wire:key to elements inside loops:

<ul>
    @foreach ($items as $item)
        <li wire:key="{{ $loop->index }}">{{ $item }}</li>
    @endforeach
</ul>

Add key() to nested components in a loop

<ul>
    @foreach ($items as $item)
        @livewire('view-item', ['item' => $item], key($loop->index))

        <!-- key() using Laravel 7's tag syntax -->
        <livewire:view-item :item="$item" :wire:key="$loop->index">
    @endforeach
</ul>

Wrap Blade conditionals (@if, @error, @auth) in an element

<input type="text" wire:model="name">
<div> @error('name'){{ $message }}@enderror </div>

Add wire:key. As a final measure, adding wire:key will directly tell Livewire how to keep track of a DOM element. Over-using this attribute is a smell, but it is very useful and powerful for problems of this nature.

<div wire:key="foo">...</div>
<div wire:key="bar">...</div>
3 likes
ojsoft's avatar

@Logendher Gunasekaran Thank you so much... the tip with wrapping blade conditionals in saved my life. The other stuff I did already.

1 like
Logendher Gunasekaran's avatar

sorry i unable to add links here i copy pasted that content from documentation of livewire

go through in reference and troubleshooting section

adityar15's avatar

@logendher gunasekaran It also says a similar thing on Livewire's official document. When I used :wire:key according to the document it works sometimes but for the other times :key is the solution.

key() seems to be the perfect solution which means the most reliable way to use the livewire component is by using @livewire syntax rather than <livewire:component_name />

1 like
Ianbrucey's avatar

setting a random key worked for me

@php($key = rand(11111,99999))

@livewire('comment-section-component', ['post' => $post, 'timeline' => $timeline], key($key))

2 likes
jamesautodude's avatar

@Ianbrucey This worked for me to but the problem arises when the component is re-rendered and you may want something to remain open like a modal, then it causes problems with the view...

For me, I got rid of the stupid $loop->index thing. That actually makes it worse and is a bad idea

You want to make the beginning div to have the ID of your loop...

For instance:

@foreach($posts as $post)

	<div wire:key="$post->id">

			<!-- remaining code inside of here -->

			<livewire:edit-post :post="$post" :wire:key="$post->id" />

	</div>

@endforeach

Problem seems to be fixed for now

If you have more than one inside of the , then put something like:

:wire:key="$post->id . 'edit' . $post->id"

Snapey's avatar

@jamesautodude using random number, or loop index are both bad ideas and are unlikely to work in all circumstances. The wire:key nust be a value or string that is a permanent relationship with the data (such as an id) so that if lines in your loop are removed then Livewire can notice the missing or added keys.

As I'm here, to answer the original question

  • wire:key on a repeated element
  • :key when you need to pass a key into a livewire component
ojsoft's avatar

@Snapey You are right. Best use UUIDs on your models, these can than be directly used as the key without the need to add something extra for all livewire elements that relate to a model. Very handy.

Please or to participate in this conversation.