owf
owf

Reputation: 251

Livewire performing double queries

I'm checking the laravel-debugbar and found that the amount of queries is twice as it should be (in my opinion)

Laravel debugbar : laravel-debugbar

While it should be called only once when rendering the view,

The Livewire Class :

class AllTodos extends Component
{
    use WithPagination;

    public $todoId;

    protected $listeners = [
        'todoAdded' => '$refresh',
        'deleteConfirmed' => 'delete',
        'completeConfirmed' => 'complete'
    ];

    public function deleteConfirmation($id)
    {
        $this->todoId = $id;
        $this->dispatchBrowserEvent('alertConfirmation', [
            'message' => 'Are you sure want to delete this task ?',
            'action' => 'deleteConfirmed'
        ]);
    }

    public function delete()
    {
        $todo = Todo::findOrFail($this->todoId);
        $todo->delete();

        $this->dispatchBrowserEvent('alertInfo', [
            'message' => 'Todo has been deleted.',
            'icon' => 'success'
        ]);
    }

    public function completeConfirmation($id)
    {
        $this->todoId = $id;

        $this->dispatchBrowserEvent('alertConfirmation', [
            'message' => 'Are you sure want to complete this task ?',
            'action' => 'completeConfirmed'
        ]);
    }

    public function complete()
    {
        $todo = Todo::findOrFail($this->todoId);
        $todo->update([
            'is_completed' => 1
        ]);

        $this->dispatchBrowserEvent('alertInfo', [
            'message' => 'Todo has been completed.',
            'icon' => 'success'
        ]);
    }

    public function render()
    {
        return view('livewire.all-todos', [
            'todos' => Todo::latest()->paginate(5)
        ]);
    }
}

The view :

<div>
    <livewire:add-todo />
    <table class="w-full m-4">
        <thead class="text-md font-semibold tracking-wide text-left text-gray-900 bg-gray-100 uppercase border-b border-gray-600">
            <th class="px-4 py-3">Title</th>
            <th class="px-4 py-3">Action</th>
        </thead>
        <tbody class="bg-white">
            @foreach($todos as $todo)
                <tr class="text-gray-700">
                    <td class="px-4 py-3 border">{{ $todo->title }}</td>
                    <td class="px-4 py-3 border">
                        <button class="p-2 pl-5 pr-5 transition-colors duration-700 transform bg-indigo-500 hover:bg-blue-400 text-gray-100 text-lg rounded-lg focus:border-4 border-indigo-300" wire:click.prevent="completeConfirmation({{ $todo->id }})">Complete</button>
                        <button class="p-2 pl-5 pr-5 transition-colors duration-700 transform bg-red-500 hover:bg-red-400 text-gray-100 text-lg rounded-lg focus:border-4 border-red-300" wire:click="deleteConfirmation({{ $todo->id }})">Delete</button>
                    </td>
                </tr>
            @endforeach    
        </tbody>
    </table>
    <div class="m-4">
        {{ $todos->links() }}
    </div>
</div>

Update

The layouts :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <link href="{{ asset('css/app.css') }}" rel="stylesheet" type="text/css" />

    @livewireStyles
    <script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
</head>
<body>
    <section class="container mx-auto p-6 font-mono">
        <div class="w-full mb-8 overflow-hidden rounded-lg shadow-lg">
            <div class="w-full overflow-x-auto">
                <livewire:all-todos />
            </div>
        </div>            
    </section>

    <x-alerts />

    <script src="{{ asset('js/swal.js') }}"></script>
    
    @stack('js')

    @livewireScripts
</body>
</html>

I tried to use mount special method, its resulting this same double queries, How to reduce these amount of queries ?

Upvotes: 1

Views: 1873

Answers (1)

Qirel
Qirel

Reputation: 26490

As we figured out in the comments, the issue here is that you don't have a slot in your layout - which is where the full-page Livewire component is injected. Instead, you render the component directly in your layout using <livewire:all-todos />.

This means two things,

  1. Your component is called twice (but only rendered once, since there is no slot for the full-page component, but the in-line rendering works as expected)
  2. Your all-todos component will be rendered on all your pages that uses that layout.

This first point here, is why you are getting double queries.

The solution

To solve your issue, you simply have to replace the inline rendering of the compoinent which is <livewire:all-todos /> with the magic variable {{ $slot }}.

<section class="container mx-auto p-6 font-mono">
    <div class="w-full mb-8 overflow-hidden rounded-lg shadow-lg">
        <div class="w-full overflow-x-auto">
            {{ $slot }}
        </div>
    </div>            
</section>

Related reading material,

Upvotes: 1

Related Questions