⚡ Tutorial

Getting Started with Laravel Livewire 3: Building Reactive Components

Livewire 3 changes the game for full-stack Laravel devs. In this walkthrough we build a reactive search component from scratch — state, hydration, lazy loading, and the new wire:model.live behaviour — without writing a single line of Vue or React.

Ilham Muttaqien Ilham Muttaqien
· 24 May 2026 · 8 min read · 2.4k views

Why Livewire Changed Everything for Me

Before Livewire, adding real-time behaviour to a Laravel app meant context-switching to Vue or React. That's fine for SPAs, but for the CRUD-heavy admin panels and government dashboards I build for clients across Indonesia, a full JavaScript framework is overkill.

Livewire 3 is Caleb Porzio's third major iteration. It ships with a fundamentally different hydration strategy — Snapshot Morphing — that fixes the flicker and full-component re-render issues that haunted v2. In this article we'll build a reactive search component from scratch and explore what makes v3 feel genuinely different.

Setting Up a Fresh Livewire 3 Project

Install via Composer, then publish the config once:

composer require livewire/livewire
php artisan livewire:publish --config

Script and style injection happens automatically via @livewireStyles and @livewireScripts in your layout. No Vite plugin or manual asset steps required.

Building a Reactive Search Component

Let's build a product search that debounces input and paginates results in real time. First, generate the component:

php artisan make:livewire ProductSearch

Then fill in the class:

namespace App\Livewire;

use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Product;

class ProductSearch extends Component
{
    use WithPagination;

    public string $search = '';

    public function updatingSearch(): void
    {
        $this->resetPage();
    }

    public function render()
    {
        return view('livewire.product-search', [
            'products' => Product::search($this->search)->paginate(12),
        ]);
    }
}

Key v3 difference: Public properties are declared directly on the class with no magic array. The #[Url] attribute replaces the old $queryString approach for URL persistence — cleaner and IDE-friendly.

The wire:model.live Behaviour

The new wire:model.live syncs state on every input event with built-in debounce support, replacing the v2 defer / lazy split:

<input
    wire:model.live.debounce.350ms="search"
    type="search"
    placeholder="Search products…"
    class="w-full border rounded-lg px-4 py-2"
/>

The .350ms suffix means Livewire waits 350 milliseconds after the last keystroke before dispatching a network request. Tune this to taste — I usually land between 300–500ms for search fields.

Skeleton Loading States

Livewire 3's wire:loading directive makes skeleton UIs trivial to implement:

{{-- Shown while re-rendering --}}
<div wire:loading class="animate-pulse space-y-3">
    <div class="h-8 bg-gray-200 rounded"></div>
    <div class="h-4 bg-gray-100 rounded w-3/4"></div>
</div>

{{-- Hidden while loading --}}
<div wire:loading.remove>
    @foreach ($products as $product)
        <x-product-card :product="$product" />
    @endforeach
</div>

You can scope loading indicators to specific actions using wire:target="search", so a spinner only appears next to the search input rather than blanking the whole page.

Computed Properties: Memoised Per Request

One of my favourite v3 features is the #[Computed] attribute. Use it for anything derived from state — results are cached for the lifetime of the request:

use Livewire\Attributes\Computed;

#[Computed]
public function stats(): array
{
    return [
        'total'    => $this->products->total(),
        'showing'  => $this->products->count(),
    ];
}

Then in your Blade template: {{ $this->stats['total'] }}. No redundant DB queries.

Things I'd Do Differently

  • Keep Livewire for state, Blade for structure. Don't nest business logic inside component templates.

  • Avoid deep component nesting. Morphing handles it, but each extra level adds latency on slow mobile connections.

  • Profile with Telescope. Livewire requests show up as separate HTTP calls — easy to spot N+1 issues before they hit production.

Conclusion

Livewire 3 delivers on its promise of reactive UIs without leaving PHP. For most Laravel projects I take on — government portals, admin panels, e-learning platforms — it's the right trade-off between developer experience and runtime complexity.

The next time a client asks for "a bit of interactivity," you can reach for Livewire 3 instead of spinning up a full Vue or React build pipeline. Your future self (and your deploy pipeline) will thank you.

Tags #laravel #livewire #php
Share
Ilham Muttaqien
Ilham Muttaqien
Web Developer · Bandung, Indonesia

Building modern web applications and information systems for government agencies, educational institutions, and businesses.