laravellaravel-livewire

Laravel Livewire - How to force child component refresh


I'd like to refresh the child component when the parent is updated and only the child component of this component should update, because I'd like to reuse the child component somewhere else in the page. The components structure is the following.

UserShow.php

class UserShow extends Component
{
    public User $user;
    public int $userId;

    public function mount() {
        $this->user = User::first();
    }

    public function updatedUserId() {
        $this->user = User::find($this->userId);
    }

    public function render() {
        return view('livewire.user-show');
    }
}
<div>
    <select wire:model="userId">
        <option value="1">Matteo</option>
        <option value="2">Giulia</option>
        <option value="3">Mattia</option>
    </select>

    <div>
        Name: {{ $user->name }}
        @livewire('user-show-email', ['user' => $user])
    </div>
</div>

UserShowEmail.php

class UserShowEmail extends Component
{
    /** @var User */
    public $user;

    public function render() {
        return view('livewire.user-show-email');
    }
}
<div>
    Email: {{ $user->email }}
</div>

When the user in UserShow is changed via updatedUserId() method, I'd like that $user prop in UserShowEmail will change accordingly. By reading the docs it seems that Livewire is not able to automatically refresh the child component.

I wonder if there's a workaround, or something that allow me to refresh the child component when parent changed.

Thanks!


Solution

  • If you don't mind updating the whole child component, this would be one way of doing it:

    There's a trick that always work for me when I want to make a child Livewire component "reactive". In your parent livewire component you use a timestamp for the key attribute:

    <livewire:child-component key="{{ now() }}" :my-prop="$myModel" />

    The tricky part is the now() function in key prop. This component now will always be updated when the parent is updated.

    In your parent component:

    <div>
        ...
    
        <div>
            Name: {{ $user->name }}
            <livewire:user-show-email key="{{ now() }}" :user="$user" />
        </div>
    </div>
    

    You can read more about it here and here.