This is a tricky issue, I tried to make an example as simple as possible.
In a Livewire component, I have an Alpinejs Component.
Inside this Alpinejs component i have a foreach.
Inside this foreach, i have multiple nested Livewire childs components, that are simple modals handled by Alpinejs and the @entangle to open and close the modal.
I know i can handle the modal only with Alpinejs here, but this is just an example to illustrate the issue.
If the elements inside the foreach are updated by Livewire, so some appears and others disappears, I have this error in the console :
index.js:29 Uncaught (in promise) TypeError: Cannot read property '$wire' of undefined
at Livewire.value (index.js:29)
at eval (eval at l (alpine.js:115), <anonymous>:3:79)
at l (alpine.js:115)
at new fe (alpine.js:1411)
at alpine.js:1556
at alpine.js:1538
at e (alpine.js:87)
at e (alpine.js:91)
at e (alpine.js:91)
at fe.walkAndSkipNestedComponents (alpine.js:1532)
<?php
namespace App\Http\Livewire;
use App\User;
use Livewire\Component;
class ParentComponent extends Component
{
public string $search = '';
protected $queryString = [
'search' => ['except' => ''],
];
public function render()
{
return view('livewire.parent-component', [
'users' => $this->search == '' ? User::all() : User::where('name', 'like', '%'.$this->search.'%')->get(),
]);
}
}
parent-component.blade.php :
<div>
<input wire:model="search" type="text" name="search" id="search" placeholder="Search users by name" autocomplete="off">
<ul x-data="{ open: false }">
<li>
<button x-on:click="open = true">Show the text</button>
<p x-show="open">
Hi, I am the text !
<button x-on:click="open = false">Close me</button>
</p>
</li>
@foreach ($users as $user)
<li wire:key="{{ $user->id }}">
<p>
{{ $user->name }}
</p>
<livewire:modal :key="'user-'.$user->id" />
</li>
@endforeach
</ul>
</div>
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Modal extends Component
{
public bool $showModal = false;
public function render()
{
return view('livewire.modal');
}
public function showModal(): void
{
$this->showModal = true;
}
public function hideModal(): void
{
$this->showModal = false;
}
}
modal.blade.php :
<div x-data="{ show: @entangle('showModal') }">
<button wire:click="showModal()">Show the modal</button>
<div x-show="show">
Hi, I am the modal !
<button wire:click="hideModal()">Close me</button>
</div>
</div>
At the first page's visit, you can play with Alpinejs showing/hiding the text and the modals.
Try to search a user to update the users' list, normally it will works again.
And then empty the search field to show all the users again, the issue will appear in the console.
I know that without using @entangle here i have no issue but in my real life component this is simpler than using browser events to close the modal.
Context
Also running into this issue.
I temporarily fix this bug by using @this instead of $wire from the child component (same behavior as v1).
Same issue, seems like alpine component is reinitialized before livewire component.$wire is ready.
I believe this has been fixed in the next version of Livewire v2.3.0 - I will likely be tagging it this week. At that time, please test and verify, if it's not fixed, please re-submit. Thank you!
I got little workaround waiting to delay x-data loading.
LivewireNestedComponent.blade.php
<div wire:init="$set('lazyLoadedNestedComponent', 1)">
@if($lazyLoadedNestedComponent)
<div x-data="{}">
...
</div>
@endif
</div>
Issue still exists in v2.3.0. When I'm using @entangle there is an error: Cannot read property '$wire' of undefined.
Same issue here
@calebporzio tried to find solutions, but it must hold x-data reactivity until wire component is loaded,
馃憢 Oh Hi! I'm Squishy, the friendly jellyfish that manages Livewire issues.
I see this issue has been closed.
Here in the Livewire repo, we have an "issues can be closed guilt-free and without explanation" policy.
If for ANY reason you think this issue hasn't been resolved, PLEASE feel empowered to re-open it.
Re-opening actually helps us track which issues are a priority.
Reply "REOPEN" to this comment and we'll happily re-open it for you!
(More info on this philosophy here: https://twitter.com/calebporzio/status/1321864801295978497)
REOPEN
We still have this issue in v2.3.1. I will see if i can reproduce this and send you a failing test PR. Thank you.
<div x-data="{ delayed : 0 }" x-init="requestAnimationFrame(() => delayed = 1)">
<template x-if="delayed">
{{ $slot }}
</template>
</div>
Alpinejs must be delayed / deferred.
I cannot use nested components in laravel playground to show the problem.
You can reproduce it when @entangle is used withiin nested compontent, and nested compontent is wire:keyed with random id to force rerender it. While rerender, he's got new Livewire.Id, then alpine is inserted in DOM, then mutation observer initialize and clone alpine compontent, but entagle points to uninitialized new Livewire component.
Delaying alpinejs component as above, ensure that livewire is initialized.
regards
psos
I noticed that this is happening when i have a model property in entangle (array is working fine)
<livewire:admin.store.order.order-status :order="$model" :edit="$edit"/>
class OrderStatus extends Component
{
protected $listeners = [];
public $edit;
public $order;
public $o = [
'pickup_store_id' => null,
'payment_method' => null,
];
public function mount($order, $edit)
{
$this->order = $order;
$this->edit = $edit;
$this->o['pickup_store_id'] = $this->order->pickup_store_id;
$this->o['payment_method'] = $this->order->payment_method;
}
This is ok
<div x-data="{ pickupStoreIDSelect: @entangle('o.pickup_store_id'), paymentMethodSelect: @entangle('o.payment_method') }" x-init="initOrderStatus">
This is not ok
<div x-data="{ pickupStoreIDSelect: @entangle('order.pickup_store_id'), paymentMethodSelect: @entangle('order.payment_method') }" x-init="initOrderStatus">
alpine.js?version=1604647548:1873 Uncaught SyntaxError: Unexpected token u in JSON at position 0
Nested property is another failing case.
bump!
@calebporzio, waiting for good news from you
I have the same problem and I can't for the life of me understand why it's happening, I cloned the user settings as an example and they do work inside my model, but then when I use mine I get alpine.js:1873 Uncaught TypeError: Cannot read property '$wire' of undefined no matter what I do
Still error:
index.js:64 Uncaught (in promise) TypeError: Cannot read property '$wire' of undefined
at Livewire.value (index.js:64)
in livewire 2.3.2
馃
Most helpful comment
Issue still exists in v2.3.0. When I'm using
@entanglethere is an error:Cannot read property '$wire' of undefined.