Episode pembuka musim ini benar-benar saya nanti-nantikan. Di Belajar Laravel #25 saya sudah menandai Livewire sebagai langkah pertama setelah dasar selesai, dan hari ini saya mulai dari situ: Livewire, komponen yang bisa berinteraksi dengan user tanpa saya harus menulis JavaScript berat. Catatan ini saya susun sambil mencoba langsung di proyek kecil, jadi sebagian besar isinya adalah pengalaman pertama saya sendiri.

Livewire itu apa, sejujurnya
Selama musim 1, setiap kali ada interaksi — tombol yang mengubah data, form yang divalidasi sebagian, pencarian yang menyaring tabel — saya selalu terbentur ke satu hal yang sama: menulis JavaScript, mengirim fetch ke endpoint API, lalu menyisipkan hasilnya ke DOM lewat innerHTML. Alurnya benar, tapi capek dan gampang salah tempat.
Livewire membalik cara kerja itu. Komponennya hidup di server, bukan di browser. Saya menulis class PHP + Blade seperti biasa, lalu Livewire yang mengurus bagian browsernya: menangkap klik, mengirimnya ke server lewat AJAX, merender ulang Blade, dan menyalin hanya bagian HTML yang berubah. Analogi yang paling pas di kepala saya: komponennya seperti pegawai kantor yang selalu siap di telepon — saya cukup bilang “tambah satu”, dia yang menghitung, saya hanya menerima hasil tampilannya.
Hasilnya, state (data komponen) tetap di server. Saya tidak perlu lagi sinkron antara variabel JavaScript dan variabel PHP — satu sumber kebenaran saja.
Mulai: instalasi dan komponen pertama
Instalasinya cukup satu perintah Composer, tanpa konfigurasi khusus:
composer require livewire/livewire php artisan make:component Counter
Perintah kedua membuat dua file: class komponen di app/Livewire/Counter.php dan tampilannya di resources/views/livewire/counter.blade.php. Isi class-nya kira-kira seperti ini:
<?php
namespace App\Livewire;
use Livewire\Component;
class Counter extends Component
{
public int $count = 0;
public function increment(): void
{
$this->count++;
}
public function decrement(): void
{
$this->count--;
}
public function render()
{
return view('livewire.counter');
}
}Yang menarik: semua properti public di class ini otomatis “terlihat” oleh Blade dan terikat dua arah dengan halaman user. Tidak ada endpoint tambahan, tidak ada state management library.
Component lifecycle: apa yang terjadi di balik layar
Bagian ini yang paling lama saya pahami. Livewire punya siklus hidup sendiri, mirip tapi tidak sama dengan lifecycle framework JavaScript:
- mount() — dipanggil sekali saat komponen pertama kali dirender. Tempat menerima parameter awal, misalnya dari URL. Setelah itu tidak dipanggil lagi, walau user berinteraksi.
- hydrate() — dipanggil setiap kali request dari browser diterima, sebelum state dipulihkan dari server.
- render() — menghasilkan Blade. Selalu dipanggil di setiap request.
- updated($property, $value) — dipanggil ketika sebuah properti berubah lewat
wire:model. Ini tempat saya menambahkan validasi ringan atau efek samping. - hydrate/hydrateProperties dan finalizeHydration — tahap lebih dalam yang jarang saya sentuh, biasanya hanya saat butuh akses request mentah.
Yang sering bikin saya bingung di awal: mount() hanya sekali, jadi kalau saya menaruh logika inisialisasi di render(), logika itu jalan terus tiap kali user menekan tombol. Setelah sadar pola ini, saya pindahkan semua inisialisasi ke mount().
Binding, event, dan wire:loading
Di tampilan, semua interaksi ditulis sebagai atribut wire:*. Ini potongan Blade untuk komponen Counter di atas:
<div>
<button wire:click="increment">Tambah</button>
<span>{{ $count }}</span>
<input wire:model.live="search" placeholder="Cari..." />
<button wire:click="decrement"
wire:target="decrement"
wire:loading.attr="disabled">
Kurangi
</button>
</div>Tiga atribut ini yang paling sering saya pakai:
- wire:model — mengikat input ke properti PHP. Varian
.livemengirim perubahan tiap ketikan (cocok untuk pencarian), tanpa varian hanya dikirim saat form disubmit — ini yang saya pilih agar server tidak kebanjiran request. - wire:click — memanggil method di class saat tombol diklik. Bisa juga
wire:submit.preventuntuk form, supaya reload halaman tidak terjadi. - wire:loading — menampilkan status “sedang memproses”.
wire:loading.attr="disabled"membuat tombol nonaktif selama request berjalan, danwire:loading.showmenampilkan elemen spinner. Ini penyelamat: tanpa ini, user bisa klik lima kali dan server menerima lima request.
Untuk komunikasi antar-komponen saya memakai event ala JavaScript: $dispatch('toast', ['pesan' => 'Tersimpan']) di satu komponen, lalu wire:on-toast di komponen lain. Filosofinya sengaja dibuat mirip JavaScript supaya saya tidak perlu belajar konsep baru yang aneh.
Catatan penting: Livewire 4
Saat saya menulis ini, versi stabil Livewire adalah seri 4.x (rilis terbaru yang saya lihat v4.4.8, Oktober 2026). Ada beberapa perubahan yang saya catat supaya tidak kaget: komponen kini bisa ditulis sebagai satu file (PHP dan Blade menyatu), halaman penuh memakai Route::livewire() alih-alih Route::get(), dan wire:model hanya mendengar event langsung dari elemennya (butuh .deep kalau mau perilaku lama). Konsep dasar yang saya tulis di atas tetap berlaku, jadi tidak perlu khawatir belajar ulang.
Kapan Livewire, kapan tidak
Pelajaran paling mahal yang saya ambil: Livewire bukan jawaban untuk semua hal. Kalau halamannya statis dan hanya butuh link, Blade biasa sudah cukup dan jauh lebih cepat. Kalau butuh animasi berat atau aplikasi mirip desktop, Inertia + Vue (episode berikutnya) lebih masuk akal. Livewire paling pas untuk CRUD admin, form kompleks, dan widget interaktif di dalam halaman yang sebagian besar kontennya tetap. Menurut saya ini posisi yang paling sering muncul di proyek nyata, makanya Livewire saya tempatkan paling awal di musim 2.
Buat saya, cara termudah memulai adalah satu komponen kecil dulu — counter, lalu form, baru tabel dengan pencarian. Setelah pola mount → render → wire:* terasa alami, sisanya tinggal membaca dokumentasi. Itu yang akan saya lanjutkan di episode berikutnya.
Komentar Terbaru