Saltearse al contenido

Ciclo de vida Hooks

Livewire proporciona una variedad de Hooks de ciclo de vida que le permiten ejecutar código en puntos específicos durante el ciclo de vida de un componente. Estos Hooks permiten realizar acciones antes o después de determinados eventos, como inicializar el componente, actualizar propiedades o renderizar la plantilla.

Esta es una lista de todos los hooks disponibles para el ciclo de vida de los componentes:

MétodoDescripción
mount()Se ejecuta cuando se crea un componente
hydrate()Llamada cuando un componente se rehidrata al inicio de una solicitud posterior.
boot()Llamada al principio de cada petición. Tanto la inicial como las siguientes
updating()Se ejecuta antes de actualizar una propiedad del componente
updated()Llamada después de actualizar una propiedad
rendering()Llamada antes de llamar a render()
rendered()Llamada después de llamar a render()
dehydrate()Llamada al final de cada solicitud de componente
exception($e, $stopPropagation)Llamada cuando se lanza una excepción

Mount

En una clase PHP estándar, un constructor (__construct()) toma parámetros externos e inicializa el estado del objeto. Sin embargo, en Livewire, usas el método mount() para aceptar parámetros e inicializar el estado de tu componente.

Los componentes Livewire no utilizan __construct() porque los componentes Livewire son reconstruidos en peticiones de red posteriores, y sólo queremos inicializar el componente una vez cuando se crea por primera vez.

He aquí un ejemplo de uso del método mount() para inicializar las propiedades nombre y email de un componente ActualizarPerfil:

use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class ActualizarPerfil extends Component
{
public $nombre;
public $email;
public function mount()
{
$this->nombre = Auth::user()->nombre;
$this->email = Auth::user()->email;
}
// ...
}

Como se mencionó anteriormente, el método mount() recibe datos pasados al componente como parámetros del método:

use Livewire\Component;
use App\Models\Publicacion;
class ActualizarPublicacion extends Component
{
public $titulo;
public $contenido;
public function mount(Publicacion $publicacion)
{
$this->titulo = $publicacion->titulo;
$this->contenido = $publicacion->contenido;
}
// ...
}

El método mount() es una parte crucial del uso de Livewire. La siguiente documentación proporciona más ejemplos del uso del método mount() para realizar tareas comunes:

Boot

Por muy útil que sea mount(), sólo se ejecuta una vez por ciclo de vida del componente, y puede que quiera ejecutar lógica al principio de cada petición al servidor para un componente dado.

Para estos casos, Livewire proporciona un método boot() donde puede escribir código de configuración del componente que pretende ejecutar cada vez que la clase del componente se inicie: tanto en la inicialización como en las peticiones posteriores.

El método boot() puede ser útil para cosas como inicializar propiedades protegidas, que no persisten entre peticiones. A continuación se muestra un ejemplo de inicialización de una propiedad protegida como un modelo Eloquent:

use Livewire\Attributes\Locked;
use Livewire\Component;
use App\Models\Publicacion;
class MostrarPublicacion extends Component
{
#[Locked]
public $publicacion_id = 1;
protected Publicacion $publicacion;
public function boot()
{
$this->publicacion = Publicacion::find($this->publicacion_id);
}
// ...
}

Puede utilizar esta técnica para tener un control completo sobre la inicialización de una propiedad de componente en su componente Livewire.

Update

Los usuarios del lado del cliente pueden actualizar las propiedades públicas de muchas maneras diferentes, más comúnmente modificando una entrada con wire:model en ella.

Livewire proporciona hooks convenientes para interceptar la actualización de una propiedad pública para que pueda validar o autorizar un valor antes de que se establezca, o asegurarse de que una propiedad se establece en un formato determinado.

A continuación se muestra un ejemplo de uso de updating para evitar la modificación de la propiedad $publicacion_id.

Vale la pena señalar que para este ejemplo en particular, en una aplicación real, debe utilizar el atributo #[Locked] en su lugar, como en el ejemplo anterior.

use Livewire\Component;
class MostrarPublicacion extends Component
{
public $publicacion_id = 1;
public function updating($propiedad, $valor)
{
// $propiedad: El nombre de la propiedad actual que se está actualizando
// $valor: El valor que se va a asignar a la propiedad
if ($propiedad === 'publicacion_id') {
throw new Exception;
}
}
// ...
}

El método anterior updating() se ejecuta antes de que se actualice la propiedad, lo que le permite detectar entradas no válidas y evitar que se actualice la propiedad. A continuación se muestra un ejemplo de uso de updated() para asegurar que el valor de una propiedad se mantiene constante:

use Livewire\Component;
class CrearUsuario extends Component
{
public $nombre_usuario = '';
public $email = '';
public function updated($propiedad)
{
// $propiedad: El nombre de la propiedad actual que se actualizó
if ($propiedad === 'nombre_usuario') {
$this->nombre_usuario = strtolower($this->nombre_usuario);
}
}
// ...
}

Ahora, cada vez que la propiedad $nombre_usuario se actualice del lado del cliente, nos aseguraremos de que el valor siempre esté en minúsculas.

Dado que a menudo nos dirigimos a una propiedad específica cuando utilizamos hooks de actualización, Livewire nos permite especificar el nombre de la propiedad directamente como parte del nombre del método. Aquí está el mismo ejemplo de arriba pero reescrito utilizando esta técnica:

use Livewire\Component;
class CrearUsuario extends Component
{
public $nombre_usuario = '';
public $email = '';
public function updatedNombreUsuario()
{
$this->nombre_usuario = strtolower($this->nombre_usuario);
}
// ...
}

Por supuesto, también puede aplicar esta técnica al hook de updating

Arrays

Las propiedades de arrays tienen un argumento adicional $clave que se pasa a estas funciones para especificar el elemento que cambia.

Tenga en cuenta que cuando se actualiza la propia matriz en lugar de una clave específica, el argumento $clave es nulo.

use Livewire\Component;
class ActualizarPreferencias extends Component
{
public $preferencias = [];
public function updatedPreferencias($valor, $clave)
{
// $valor = 'dark'
// $clave = 'theme'
}
// ...
}

Hydrate & Dehydrate

Hydrate & Dehydrate son hooks menos conocidos y utilizados. Sin embargo, hay escenarios específicos donde pueden ser poderosos.

Los términos “Dehydrate” e “Hydrate” se refieren a un componente Livewire que se serializa a JSON para el lado del cliente y luego se vuelve a deserializar a un objeto PHP en la solicitud posterior.

A menudo usamos los términos “Hydrate” y “Dehydrate” para referirnos a este proceso a través del código base de Livewire y la documentación. Si desea más claridad sobre estos términos, puede aprender más consultando nuestra documentación de hidratación.

Veamos un ejemplo que utiliza mount() , hydrate() y dehydrate() conjuntamente para soportar el uso de un objeto de transferencia de datos personalizado (DTO) en lugar de un modelo Eloquent para almacenar los datos de la entrada en el componente:

use Livewire\Component;
class MostrarPublicacion extends Component
{
public $publicacion;
public function mount($titulo, $contenido)
{
// Se ejecuta al principio de la primera petición inicial...
$this->publicacion = new PublicacionDto([
'titulo' => $titulo,
'contenido' => $contenido,
]);
}
public function hydrate()
{
// Se ejecuta al principio de cada petición «subsiguiente»...
// No se ejecuta en la petición inicial («mount» sí)...
$this->publicacion = new PublicacionDto($this->publicacion);
}
public function dehydrate()
{
// Se ejecuta al final de cada solicitud...
$this->publicacion = $this->publicacion->toArray();
}
// ...
}

Ahora, desde las acciones y otros lugares dentro de su componente, puede acceder al objeto PublicacionDto en lugar de a los datos primitivos.

El ejemplo anterior demuestra principalmente las habilidades y la naturaleza de los hooks hydrate() y dehydrate(). Sin embargo, se recomienda utilizar Wireables o Synthesizers para lograr esto en su lugar.

Render

Si quieres hook al proceso de renderizado de la vista Blade de un componente, puedes hacerlo utilizando los hooks rendering() y rendered():

use Livewire\Component;
use App\Models\Publicacion;
class MostrarPublicaciones extends Component
{
public function render()
{
return view('livewire.mostrar-publicaciones', [
'publicaciones' => Publicacion::all(),
])
}
public function rendering($view, $data)
{
// Se ejecuta ANTES de renderizar la vista proporcionada...
//
// $view: La vista a renderizar
// $datos: Los datos proporcionados a la vista
}
public function rendered($view, $html)
{
// Se ejecuta DESPUÉS de renderizar la vista proporcionada...
//
// $view: La vista renderizada
// $html: El HTML final renderizado
}
// ...
}

Exception

A veces puede ser útil interceptar y atrapar errores, por ejemplo: para personalizar el mensaje de error o ignorar un tipo específico de excepciones. El hook exception() le permite hacer precisamente eso: puede realizar una comprobación en el $error, y utilizar el parámetro $stopPropagation para atrapar el problema. Esto también desbloquea poderosos patrones cuando quieres detener la ejecución posterior del código (devolver antes de tiempo), así es como funcionan métodos internos como validate().

use Livewire\Component;
class MostrarPublicacion extends Component
{
public function mount()
{
$this->publicacion = Post::find($this->publicacion_id);
}
public function exception($e, $stopPropagation) {
if($e instanceof NotFoundException) {
$this->notify('No se encuentra la publicación')
$stopPropagation();
}
}
// ...
}

Usando Hooks dentro de Traits

Los traits son una forma útil de reutilizar código entre componentes o extraer código de un único componente en un archivo dedicado.

Para evitar que varios traits entren en conflicto entre sí al declarar los ciclos de vida de los Hooks, Livewire permite anteponer a los métodos de los Hooks el nombre en camelCased del trait actual que los declara.

De esta forma, puede tener múltiples rasgos utilizando los mismos ganchos de ciclo de vida y evitar definiciones de métodos conflictivos.

A continuación se muestra un ejemplo de un componente que hace referencia a un rasgo llamado HasPostForm:

use Livewire\Component;
class CrearPublicacion extends Component
{
use HasPostForm;
// ...
}

Ahora aquí está el rasgo HasPostForm real que contiene todos los Hooks prefijados disponibles:

trait HasPostForm
{
public $title = '';
public $content = '';
public function mountHasPostForm()
{
// ...
}
public function hydrateHasPostForm()
{
// ...
}
public function bootHasPostForm()
{
// ...
}
public function updatingHasPostForm()
{
// ...
}
public function updatedHasPostForm()
{
// ...
}
public function renderingHasPostForm()
{
// ...
}
public function renderedHasPostForm()
{
// ...
}
public function dehydrateHasPostForm()
{
// ...
}
// ...
}