Saltar al contenido

Livewire 4 ya está disponible y trae cambios significativos. En este artículo vamos a revisar las novedades más importantes, los breaking changes que debes tener en cuenta al migrar, y algunas opiniones personales sobre las nuevas características.

Requisitos

Los requisitos mínimos son PHP 8.1+ y Laravel 10+. Bastante accesibles. La instalación es directa con composer require livewire/livewire:^4.0 seguido de php artisan optimize:clear.


Breaking Changes de Alto Impacto

Estos son los cambios que probablemente te afecten si vienes de Livewire 3.

Configuración renombrada

En config/livewire.php, las claves layout y lazy_placeholder ahora se llaman component_layout y component_placeholder respectivamente.

Nuevo sistema de routing

Aunque la sintaxis tradicional Route::get('/dashboard', Dashboard::class) sigue funcionando, ahora se recomienda usar Route::livewire():

<?php

// Recomendado en v4
Route::livewire('/dashboard', Dashboard::class);

// Para componentes basados en vistas
Route::livewire('/dashboard', 'pages::dashboard');

wire:model ya no escucha eventos hijos

Este es un cambio importante. Si tenías un wire:model en un contenedor que escuchaba eventos de inputs hijos, ahora necesitas añadir el modificador .deep:

<!-- ANTES (v3) - escuchaba eventos de hijos automáticamente -->
<div wire:model="value">
    <input type="text">
</div>

<!-- AHORA (v4) - necesitas .deep para el mismo comportamiento -->
<div wire:model.deep="value">
    <input type="text">
</div>

Tags de componentes deben cerrarse

Los tags de componentes Livewire ahora deben cerrarse obligatoriamente:

<!-- Ya no funciona -->
<livewire:component-name>

<!-- Obligatorio en v4 -->
<livewire:component-name />

wire:scroll renombrado

Si usabas wire:scroll, ahora es wire:navigate:scroll.


Islands: La Estrella de Livewire 4

Sin duda, Islands es la característica más destacada de esta versión. Permite crear regiones aisladas dentro de un componente que se actualizan de forma independiente, sin necesidad de crear componentes hijos.

El problema que resuelve

Imagina un dashboard con estadísticas de revenue (query costosa), lista de usuarios y un gráfico. En Livewire 3, si hacías click en "Refresh" en cualquier parte, todo el componente se re-renderizaba, incluyendo las queries costosas.

La alternativa era crear componentes hijos, pero eso implica gestionar props, eventos y más archivos.

La solución

<?php

use Livewire\Attributes\Computed;
use Livewire\Component;

new class extends Component {
    #[Computed]
    public function revenue()
    {
        // Query costosa
        return Revenue::yearToDate();
    }
};
?>

<div>
    @island
        <div>
            Revenue: {{ $this->revenue }}
            <button wire:click="$refresh">Refresh</button>
        </div>
    @endisland

    <!-- Esto NO se re-renderiza cuando refrescas el island -->
    <div>
        <h2>Otra sección</h2>
        <p>Este contenido permanece intacto</p>
    </div>
</div>

Cuando haces click en "Refresh", solo el island se actualiza. El resto del componente ni se toca.

Lazy loading y defer

Los islands soportan carga diferida. Con lazy: true el contenido carga cuando entra en el viewport (scroll). Con defer: true carga inmediatamente después del page load:

@island(lazy: true)
    <div>{{ $this->expensiveData }}</div>
@endisland

@island(defer: true)
    <div>{{ $this->otherData }}</div>
@endisland

Named islands

Puedes nombrar islands y triggearlos desde cualquier parte del componente:

@island(name: 'stats')
    <div>{{ $this->stats }}</div>
@endisland

<button wire:click="$refresh" wire:island="stats">
    Actualizar estadísticas
</button>

Append y Prepend para infinite scroll

@island(name: 'feed')
    @foreach ($this->posts as $post)
        <x-post-card :post="$post" />
    @endforeach
@endisland

<button wire:click.append="loadMore" wire:island="feed">
    Cargar más
</button>

Placeholder personalizado

@island(lazy: true)
    @placeholder
        <div class="animate-pulse">
            <div class="h-32 bg-gray-200 rounded"></div>
        </div>
    @endplaceholder

    <div>{{ $this->revenue }}</div>
@endisland

Por qué Islands es tan importante

Islands resuelve elegantemente un problema real: obtener el rendimiento de componentes pequeños sin la complejidad de crearlos. No necesitas gestionar props ni eventos porque todo sigue en el mismo componente. Además, el lazy loading integrado permite diferir la carga de secciones pesadas de forma trivial.

Limitaciones de Islands

No tienen acceso a variables @php del template padre y no pueden usarse dentro de @foreach, @if u otras estructuras de control. Si necesitas un loop, ponlo dentro del island.

Para más información, consulta el artículo Livewire 4 Islands.


Nuevas Formas de Crear Componentes

Livewire 4 introduce tres formas de crear componentes.

Single-File Components (SFC)

Es el formato por defecto en v4. PHP y Blade en el mismo archivo, usando el prefijo ⚡ en el nombre:

<?php
// resources/views/livewire/⚡counter.blade.php

use Livewire\Component;

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

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

<div>
    <h1>{{ $count }}</h1>
    <button wire:click="increment">+</button>
</div>

Multi-File Components (MFC)

Clase PHP en app/Livewire y vista en resources/views/livewire. Se crean con php artisan make:livewire counter --mfc.

View-Based Components

Solo una vista Blade sin clase PHP asociada. Útil para componentes muy simples.

Mi opinión personal

Prefiero los componentes tradicionales basados en clases (multi-file). La separación de responsabilidades es más clara, el IDE funciona mejor, y el código es más fácil de navegar y mantener. Los SFC pueden parecer convenientes, pero en proyectos reales la claridad gana.


Acciones Asíncronas

Permite ejecutar acciones en paralelo sin bloquear otras peticiones:

<?php

use Livewire\Attributes\Async;

#[Async]
public function logActivity(): void
{
    // Se ejecuta sin bloquear
}
<button wire:click.async="logActivity">Track</button>

Precaución: Las acciones async pueden causar race conditions si modifican propiedades compartidas.


Lazy y Defer para Componentes

Además de los islands, puedes aplicar lazy y defer a componentes completos.

El atributo #[Lazy] hace que el componente cargue cuando entra en el viewport. El atributo #[Defer] hace que cargue inmediatamente después del page load.

También puedes usarlos en la vista con <livewire:component lazy /> o <livewire:component defer />.

Para cargar múltiples componentes en una sola petición, usa lazy.bundle:

<livewire:stats lazy.bundle />
<livewire:chart lazy.bundle />

wire:sort - Drag & Drop Nativo

Por fin tenemos drag & drop integrado sin librerías externas:

<?php

public function updateOrder($item, $position): void
{
    $todo = Todo::find($item);
    $todo->update(['order' => $position]);
}
<ul wire:sort="updateOrder">
    @foreach ($todos as $todo)
        <li wire:sort:item="{{ $todo->id }}" wire:key="{{ $todo->id }}">
            {{ $todo->title }}
        </li>
    @endforeach
</ul>

Soporta handles específicos con wire:sort:handle, elementos que no triggerean drag con wire:sort:ignore, y drag entre grupos con wire:sort:group.


wire:intersect - Intersection Observer

Ejecuta acciones cuando un elemento entra o sale del viewport:

<div wire:intersect="loadMore">...</div>
<div wire:intersect.once="trackView">...</div>
<div wire:intersect:leave="pauseVideo">...</div>
<div wire:intersect.half="loadMore">...</div>
<div wire:intersect.full="startAnimation">...</div>

Ideal para analytics, lazy loading de contenido, o infinite scroll.


Otros Cambios Notables

wire:ref

Nueva forma de referenciar elementos para usar en JavaScript:

<div wire:ref="modal">...</div>

Modificadores nuevos

El modificador .renderless ejecuta una acción sin re-renderizar el componente. El modificador .preserve-scroll mantiene la posición de scroll.

$errors en JavaScript

Ahora puedes acceder a los errores de validación desde JavaScript:

<div wire:show="$errors.has('email')">
    <span wire:text="$errors.first('email')"></span>
</div>

Mejoras de rendimiento

El polling con wire:poll ya no bloquea otras peticiones, wire:model.live ejecuta peticiones en paralelo, y smart_wire_keys viene activado por defecto.


Migración desde Volt

Si usabas Volt, ahora puedes migrar a Livewire nativo. Cambia use Livewire\Volt\Component por use Livewire\Component, elimina VoltServiceProvider y ejecuta composer remove livewire/volt. Los componentes Volt class-based funcionan sin modificación adicional.


Resumen de PHP Attributes

Attribute

Descripción

#[Async]

Ejecutar acción en paralelo

#[Computed]

Propiedad computada/memoizada

#[Defer]

Cargar después del page load

#[Lazy]

Cargar al entrar en viewport

#[Locked]

Propiedad no modificable desde cliente

#[Modelable]

Propiedad bindeable con wire:model en componente padre

#[On]

Listener de eventos

#[Reactive]

Props reactivos desde componente padre

#[Renderless]

Acción sin re-render

#[Session]

Persistir en sesión

#[Title]

Título de página

#[Url]

Persistir en query string

#[Validate]

Reglas de validación inline


Conclusión

Livewire 4 es una actualización sólida. Islands es claramente la estrella de esta versión, resolviendo elegantemente el problema de rendimiento en componentes grandes sin añadir complejidad.

Los Single-File Components son interesantes para quien venga de Vue o React, pero personalmente sigo prefiriendo los componentes basados en clases tradicionales por su mejor integración con el IDE y la separación clara de responsabilidades.

La migración desde v3 es relativamente sencilla. Los breaking changes más importantes son el cambio en wire:model (que ahora requiere .deep para escuchar eventos de hijos) y la necesidad de cerrar los tags de componentes.

Para más información, consulta la documentación oficial de Livewire 4.

school Curso completo

Curso Laravel 12
Completo 2026

El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.

access_time 8 horas de contenido
layers 4 tecnologías en 1
update 100% actualizado
code Proyectos prácticos
Ver Curso Laravel 12 arrow_forward

star Incluido en cualquier suscripción

Rutas de aprendizaje