Livewire: componentes reativos sem JavaScript
Introdução ao Livewire e seu Lugar no Ecossistema PHP
Livewire é uma biblioteca full-stack para Laravel que permite criar interfaces dinâmicas e reativas sem escrever uma única linha de JavaScript. Desenvolvido por Caleb Porzio, o Livewire funciona como uma camada que conecta o frontend Blade ao backend PHP, enviando requisições AJAX automaticamente sempre que o usuário interage com um componente.
Diferente de abordagens tradicionais como jQuery (que exige manipulação manual do DOM) ou frameworks modernos como Vue e React (que demandam conhecimento separado de JavaScript), o Livewire mantém toda a lógica no PHP. Comparado ao Inertia.js, que também reduz a necessidade de JS mas ainda requer um framework frontend, o Livewire é ainda mais "PHP-centric", funcionando exclusivamente com Blade.
Pré-requisitos: Laravel 8+, Blade, conceitos básicos de componentes e rotas.
Instalação e Primeiro Componente
A instalação é feita via Composer:
composer require livewire/livewire
Em seguida, inclua os assets do Livewire no layout principal:
<html>
<head>
@livewireStyles
</head>
<body>
@livewireScripts
</body>
</html>
Vamos criar nosso primeiro componente: um contador reativo. Primeiro, geramos o componente com o Artisan:
php artisan make:livewire Contador
Isso cria dois arquivos:
- app/Http/Livewire/Contador.php (classe PHP)
- resources/views/livewire/contador.blade.php (view Blade)
Classe do componente:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Contador extends Component
{
public $count = 0;
public function incrementar()
{
$this->count++;
}
public function decrementar()
{
$this->count--;
}
public function render()
{
return view('livewire.contador');
}
}
View Blade:
<div>
<h1>Contador: {{ $count }}</h1>
<button wire:click="incrementar">+</button>
<button wire:click="decrementar">-</button>
</div>
Para usar o componente em qualquer view:
<livewire:contador />
Ciclo de Vida e Reatividade
O Livewire possui métodos de ciclo de vida que permitem controlar o comportamento do componente:
mount()— executado uma vez na inicializaçãohydrate()— executado em cada requisição (inclusive na primeira)updating($property, $value)— antes de uma propriedade ser atualizadaupdated($property, $value)— depois de uma propriedade ser atualizadarender()— sempre que o componente é renderizado
public function mount()
{
$this->count = session('count', 0);
}
public function updating($property, $value)
{
if ($property === 'count' && $value > 100) {
$this->count = 100;
}
}
A reatividade é automática: qualquer propriedade public que for alterada dispara um re-render do componente. Modificadores como #[Computed] permitem criar propriedades computadas que não são enviadas ao frontend, mas podem ser acessadas na view:
use Livewire\Attributes\Computed;
#[Computed]
public function dobro()
{
return $this->count * 2;
}
Ações e Eventos no Frontend
As interações do usuário disparam ações no backend através de diretivas Blade:
<button wire:click="salvar">Salvar</button>
<input wire:keydown.enter="buscar">
<form wire:submit.prevent="enviar">...</form>
É possível passar parâmetros diretamente:
<button wire:click="remover({{ $item->id }})">Remover</button>
Para comunicação entre componentes, usamos eventos:
Emitindo evento:
$this->dispatch('item-atualizado', itemId: $item->id);
Escutando no frontend:
<div wire:key="item-{{ $item->id }}">
{{-- conteúdo --}}
</div>
<script>
document.addEventListener('livewire:init', () => {
Livewire.on('item-atualizado', (event) => {
alert('Item ' + event.itemId + ' atualizado!');
});
});
</script>
O wire:model oferece binding bidirecional para inputs:
<input wire:model.lazy="nome" type="text">
Modificadores como .lazy (atualiza apenas no blur), .debounce.500ms e .throttle controlam a frequência das requisições.
Validação e Formulários Reativos
O Livewire integra-se perfeitamente com o sistema de validação do Laravel:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class CadastroUsuario extends Component
{
public $nome = '';
public $email = '';
public $senha = '';
protected $rules = [
'nome' => 'required|min:3',
'email' => 'required|email|unique:users,email',
'senha' => 'required|min:8',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function salvar()
{
$this->validate();
User::create([
'nome' => $this->nome,
'email' => $this->email,
'senha' => bcrypt($this->senha),
]);
session()->flash('message', 'Usuário cadastrado com sucesso!');
$this->reset(['nome', 'email', 'senha']);
}
public function render()
{
return view('livewire.cadastro-usuario');
}
}
View com feedback em tempo real:
<form wire:submit.prevent="salvar">
<div>
<label>Nome:</label>
<input wire:model.lazy="nome" type="text">
@error('nome') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<label>Email:</label>
<input wire:model.lazy="email" type="email">
@error('email') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<label>Senha:</label>
<input wire:model.lazy="senha" type="password">
@error('senha') <span class="error">{{ $message }}</span> @enderror
</div>
<button type="submit">Cadastrar</button>
@if (session()->has('message'))
<div class="success">{{ session('message') }}</div>
@endif
</form>
Componentes Avançados e Boas Práticas
Componentes aninhados e comunicação
Componentes filhos podem emitir eventos para pais usando $emitUp:
// No componente filho
$this->dispatch('selecionado', id: $this->itemId)->to('pai-componente');
Ou diretamente no Blade:
<button wire:click="$emitUp('selecionado', {{ $item->id }})">Selecionar</button>
Traits para reutilização
trait ComPaginacao
{
public $perPage = 10;
public $page = 1;
public function proximaPagina()
{
$this->page++;
}
public function paginaAnterior()
{
$this->page = max(1, $this->page - 1);
}
}
Performance com lazy loading e polling
Para componentes que carregam dados pesados:
use Livewire\Attributes\Lazy;
#[Lazy]
public function dados()
{
return Dado::all();
}
Polling automático para atualizações em tempo real:
<div wire:poll.5s>
{{-- conteúdo que será atualizado a cada 5 segundos --}}
</div>
Testes e Depuração de Componentes Livewire
Testar componentes Livewire é simples com o helper Livewire::test():
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Livewire\Livewire;
use App\Http\Livewire\Contador;
class ContadorTest extends TestCase
{
/** @test */
public function pode_incrementar()
{
Livewire::test(Contador::class)
->assertSet('count', 0)
->call('incrementar')
->assertSet('count', 1)
->assertSee('Contador: 1');
}
/** @test */
public function valida_campo_obrigatorio()
{
Livewire::test(CadastroUsuario::class)
->set('nome', '')
->call('salvar')
->assertHasErrors(['nome' => 'required']);
}
}
Para depuração, integre com Laravel Telescope ou use o log:
public function updated($property, $value)
{
logger("Propriedade $property atualizada para $value");
}
Erros comuns:
- "Method not found" — verifique se o método existe na classe e se a diretiva wire:click está correta
- "Property not reactive" — certifique-se de que a propriedade é public e não está sendo serializada incorretamente
Considerações Finais e Comparação com Ferramentas Vizinhas
Quando usar Livewire:
- Projetos Laravel com equipe predominantemente PHP
- Formulários complexos com validação em tempo real
- Painéis administrativos e CRUDs
- Quando o time não tem expertise em JavaScript moderno
Quando considerar alternativas:
- Inertia.js — melhor para SPAs completos que exigem roteamento no frontend
- Vue/React puro — ideal para interfaces altamente interativas e complexas
- Alpine.js — complementar ao Livewire para interações leves no frontend
Limitações do Livewire:
- Dependência de conexão HTTP (cada interação gera uma requisição)
- Complexidade em componentes com muitas interações simultâneas
- Consumo maior de banda comparado a SPAs otimizados
Livewire representa uma mudança de paradigma: você obtém interatividade moderna mantendo o conforto e a produtividade do ecossistema Laravel. Para muitos projetos, especialmente aqueles focados em produtividade e manutenibilidade, Livewire é a escolha certa.
Referências
- Documentação Oficial do Livewire — Guia completo de instalação, componentes, eventos e testes
- Laravel News: Livewire Tutorial — Artigos práticos e atualizações sobre a biblioteca
- Livewire PowerGrid — Pacote complementar para tabelas e grids reativos com Livewire
- Laravel Daily: Livewire Course — Curso gratuito com exemplos de formulários, validação e componentes aninhados
- Caleb Porzio: Introdução ao Livewire (YouTube) — Vídeo do criador do Livewire demonstrando conceitos fundamentais
- Livewire Tables — Pacote popular para criação de tabelas dinâmicas com ordenação, busca e paginação
- Laravel Bootcamp: Livewire Stack — Tutorial oficial do Laravel usando Livewire para construir um aplicativo completo