Saltar al contenido principal

¿Qué es Livewire?

Cuando intentabas crear UIs dinámicas en Laravel, antes no había más remedio que combinar frameworks JavaScript como Vue.js o React, o escribir tú mismo las peticiones AJAX. Livewire es un paquete para Laravel que resuelve ese problema. Permite construir UIs reactivas solo con PHP y Blade. Puedes implementar en PHP funcionalidades que antes requerían JavaScript, como validación de formularios en tiempo real, búsqueda en vivo, contadores, etc.
Livewire 4 funciona con Laravel 10 o superior y PHP 8.1 o superior. La versión más reciente actualmente es Livewire 4.

Resumen del mecanismo

Un componente Livewire es la combinación de una clase PHP en el servidor y una plantilla Blade. Cuando el usuario hace clic en un botón o rellena un formulario, Livewire envía por debajo una petición AJAX, ejecuta PHP y refleja en la página solo la parte modificada. El desarrollador no tiene que ser consciente de este mecanismo y puede escribir todo solo con PHP.

Instalación

Ejecuta el siguiente comando en la raíz de tu aplicación Laravel.
composer require livewire/livewire
Como el autodescubrimiento de paquetes de Laravel está activo, no se necesita configuración adicional.

Creación del archivo de layout

Si vas a usarlo como componente de página completa, necesitas un archivo de layout. Puedes generarlo con el siguiente comando Artisan.
php artisan livewire:layout
Se genera resources/views/layouts/app.blade.php.
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>{{ $title ?? config('app.name') }}</title>

        @vite(['resources/css/app.css', 'resources/js/app.js'])

        @livewireStyles
    </head>
    <body>
        {{ $slot }}

        @livewireScripts
    </body>
</html>
@livewireStyles y @livewireScripts cargan automáticamente los assets de Livewire y Alpine.js.

Tu primer componente

Existe un comando Artisan para generar componentes Livewire. Vamos a crear un contador simple.
php artisan make:livewire Counter
Con este comando se genera un componente de archivo único llamado resources/views/components/⚡counter.blade.php.
El ⚡ en el nombre del archivo sirve para identificar a simple vista los componentes Livewire. Mejora la visibilidad en el editor. Si no lo necesitas, puedes desactivarlo en la configuración.
Edita el archivo generado de la siguiente manera.
<?php

use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }

    public function decrement(): void
    {
        $this->count--;
    }
};
?>

<div>
    <h1>Contador: {{ $count }}</h1>

    <button wire:click="increment">+1</button>
    <button wire:click="decrement">-1</button>
</div>
Para incrustar este componente en una plantilla Blade, se usa la sintaxis normal de componentes Blade.
<livewire:counter />
Cada vez que se hace clic en un botón, el contador se actualiza sin recargar la página. wire:click es el mecanismo para invocar un método PHP en lugar de JavaScript.

Propiedades y acciones

Propiedades — wire:model

Con la directiva wire:model puedes vincular bidireccionalmente un elemento de entrada con una propiedad del componente.
<?php

use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';
};
?>

<div>
    <input type="text" wire:model="name" placeholder="Nombre">
    <input type="email" wire:model="email" placeholder="Email">

    <p>Hola, {{ $name }} ({{ $email }})</p>
</div>
Por defecto, wire:model sincroniza con el servidor solo cuando se ejecuta una acción (por ejemplo, el envío del formulario). Si quieres que se sincronice a cada entrada, añade el modificador .live.
NotaciónComportamiento
wire:modelSincroniza solo cuando se ejecuta una acción (envío de formulario, etc.) (por defecto)
wire:model.liveEnvía una petición a cada entrada
wire:model.blurSincroniza al perder el foco (no se genera petición)
wire:model.live.blurEnvía una petición al perder el foco

Acciones — wire:click, wire:submit

wire:click liga un método al evento de clic, y wire:submit al evento de envío de formulario.
<?php

use Livewire\Component;
use App\Models\Task;

new class extends Component {
    public string $taskName = '';

    public function addTask(): void
    {
        Task::create(['name' => $this->taskName]);
        $this->taskName = '';
    }

    public function render()
    {
        return $this->view([
            'tasks' => Task::latest()->get(),
        ]);
    }
};
?>

<div>
    <form wire:submit="addTask">
        <input type="text" wire:model="taskName" placeholder="Nombre de la tarea">
        <button type="submit">Añadir</button>
    </form>

    <ul>
        @foreach ($tasks as $task)
            <li>{{ $task->name }}</li>
        @endforeach
    </ul>
</div>

Validación en tiempo real

En Livewire 4 puedes definir reglas de validación directamente en las propiedades con el atributo #[Validate].
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\Post;

new class extends Component {
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function save(): void
    {
        $this->validate();

        Post::create([
            'title' => $this->title,
            'content' => $this->content,
        ]);

        $this->reset(['title', 'content']);

        session()->flash('message', 'Se ha guardado el artículo.');
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <div>
            <input type="text" wire:model.live.blur="title" placeholder="Título">
            @error('title') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <div>
            <textarea wire:model.live.blur="content" placeholder="Contenido"></textarea>
            @error('content') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <button type="submit">Guardar</button>
    </form>
</div>
Las propiedades con #[Validate] disparan una validación automática en cada actualización. Al combinarlas con wire:model.live.blur, logras una experiencia de validación en tiempo real en la que aparece el mensaje de error justo al perder el foco.
$this->validate() verifica todas las propiedades a la vez al enviar el formulario. El patrón recomendado es usarlo en dos niveles junto con la validación automática mediante #[Validate].

Hooks del ciclo de vida

Los componentes Livewire tienen varios hooks de ciclo de vida.
HookMomento
mount()Cuando el componente se crea por primera vez (una sola vez)
boot()Al inicio de cada petición (tanto la primera como las siguientes)
updating($property, $value)Justo antes de actualizar la propiedad
updated($property)Justo después de actualizar la propiedad
rendering()Antes de renderizar la vista
rendered()Después de renderizar la vista
dehydrate()Al finalizar cada petición

mount() — Inicialización

mount() se usa para inicializar el componente. Es el equivalente al constructor.
<?php

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';

    public function mount(): void
    {
        $this->name = Auth::user()->name;
        $this->email = Auth::user()->email;
    }
};
?>

<div>
    <p>Nombre: {{ $name }}</p>
    <p>Email: {{ $email }}</p>
</div>

updated() — Procesamiento tras cambiar propiedad

Si quieres insertar procesamiento después de que se actualice una propiedad, usa updated(). Si quieres acotarlo a una propiedad concreta, inclúyela en el nombre del método.
<?php

use Livewire\Component;

new class extends Component {
    public string $username = '';

    public function updatedUsername(): void
    {
        $this->username = strtolower($this->username);
    }
};
?>

<div>
    <input type="text" wire:model.live="username">
    <p>Nombre de usuario: {{ $username }}</p>
</div>
A cada entrada, se convierte automáticamente a minúsculas.

Integración con Laravel

Uso de modelos Eloquent

Livewire puede mantener modelos Eloquent directamente como propiedades.
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\User;

new class extends Component {
    public User $user;

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

    #[Validate('required|min:2')]
    public string $name = '';

    public function save(): void
    {
        $this->validate();
        $this->user->update(['name' => $this->name]);
        session()->flash('message', 'Se ha actualizado el perfil.');
    }

    public function render()
    {
        return $this->view();
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <input type="text" wire:model="name" placeholder="Nombre">
        @error('name') <span style="color: red;">{{ $message }}</span> @enderror
        <button type="submit">Actualizar</button>
    </form>
</div>

Objetos de formulario

Los formularios complejos se pueden extraer a objetos de formulario para mantener el componente sencillo.
php artisan livewire:form PostForm
namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;
use App\Models\Post;

class PostForm extends Form
{
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function store(): void
    {
        Post::create($this->only(['title', 'content']));
    }
}
Usa el objeto de formulario desde el componente.
<?php

use App\Livewire\Forms\PostForm;
use Livewire\Component;

new class extends Component {
    public PostForm $form;

    public function save(): void
    {
        $this->form->validate();
        $this->form->store();
        $this->form->reset();
        session()->flash('message', 'Se ha creado la publicación.');
    }
};
?>

<div>
    <form wire:submit="save">
        <input type="text" wire:model="form.title" placeholder="Título">
        @error('form.title') <span style="color: red;">{{ $message }}</span> @enderror

        <textarea wire:model="form.content" placeholder="Contenido"></textarea>
        @error('form.content') <span style="color: red;">{{ $message }}</span> @enderror

        <button type="submit">Publicar</button>
    </form>
</div>

Conclusión

Resumen de los casos de uso en los que Livewire encaja especialmente bien.
Caso de usoLo que Livewire puede lograr
Procesamiento de formulariosValidación en tiempo real y muestra de errores
Listados de datosBúsqueda en vivo, ordenación y paginación
Contadores y togglesActualizar UI sin recargar la página
Panel de administraciónCRUD con integración directa con Eloquent
Formularios tipo wizardGestión de pasos implementada en PHP
Livewire lo pueden empezar a usar hoy mismo los ingenieros Laravel “que hayan usado Blade”. Su mayor fortaleza es que permite lograr UIs interactivas sin el coste de aprendizaje de un framework JavaScript. Cuando se necesitan interacciones avanzadas al nivel de una SPA, Inertia.js encaja mejor, pero para formularios, paneles de administración o tablas de datos, en muchos casos Livewire permite implementarlo de manera más simple. Empieza probando con un componente pequeño.

Documentación oficial de Livewire

Consulta la documentación oficial para todas las funcionalidades de Livewire (subida de archivos, paginación, testing, etc.).
Última modificación el 13 de julio de 2026