Aller au contenu principal

Module 7 – Lifecycle et hooks

Niveau 5.1 – Laravel Livewire


mount(), updated() / updatedPropertyName(), hydrate() / dehydrate() : à quoi ils servent et quand les utiliser. En fin de module : ordre d’exécution et optimisation de la sérialisation.


Objectif

À la fin de ce module, vous saurez :

  • Comprendre le cycle de vie d’un composant Livewire : création (premier rendu), mise à jour de propriétés, action utilisateur, re-render, et sérialisation entre les requêtes.
  • Utiliser mount() pour initialiser le composant (paramètres passés depuis la vue, données depuis la BDD, valeurs par défaut dérivées de la route ou du contexte).
  • Réagir aux changements de propriétés avec updated($property) ou updatedPropertyName() (ex. réinitialiser la pagination quand la recherche change).
  • Savoir quand utiliser hydrate() et dehydrate() pour des cas avancés (nettoyer ou enrichir l’état sérialisé, éviter de sérialiser des objets lourds).

Cycle de vie en bref

  1. Premier chargement : la page Blade est rendue ; le composant est instancié, mount() est appelé (si défini), puis render(). Le HTML est envoyé au client ; Livewire hydrate le composant côté navigateur (attache les écouteurs, enregistre l’état).
  2. Action utilisateur (wire:click, wire:submit, ou mise à jour wire:model) : le client envoie une requête AJAX avec l’état sérialisé du composant et l’action à exécuter.
  3. Côté serveur : Livewire désérialise l’état (remplit les propriétés publiques), appelle éventuellement hydrate(), exécute la méthode demandée (ou met à jour les propriétés pour wire:model), appelle updated()* si des propriétés ont changé, puis render(). La réponse (nouveau HTML ou diff) est renvoyée.
  4. Côté client : le DOM est mis à jour (morphing). L’état est conservé pour la prochaine interaction.

Les hooks sont des points d’accroche pour exécuter du code à des moments précis de ce cycle.


mount() : initialisation au premier rendu

mount() est appelé une seule fois : à la création du composant (premier rendu de la page). C’est l’équivalent d’un constructeur pour la logique d’initialisation. Vous pouvez y accepter des paramètres passés depuis la vue (ex. <livewire:post-detail :post-id="$post->id" />).

Signature : public function mount(...params): void

Exemple : composant qui affiche un article ; l’ID est passé depuis la vue ou la route.

public function mount(int $postId): void
{
$this->post = Post::findOrFail($postId);
}

public function render()
{
return view('livewire.post-detail', ['post' => $this->post]);
}

Dans la vue qui inclut le composant :

<livewire:post-detail :post-id="$post->id" />

Les paramètres de mount() ne sont pas automatiquement stockés dans des propriétés publiques ; si vous avez besoin de $postId plus tard (sérialisé entre les requêtes), assignez-le à une propriété publique dans mount() : $this->postId = $postId;. Ici, $post est chargé une fois ; si vous le mettez dans une propriété publique $post, il sera sérialisé (Livewire gère les modèles Eloquent en les stockant par ID et en les réhydratant). Pour un composant en lecture seule, charger dans mount() et passer à la vue via render() suffit souvent.


updated() et updatedPropertyName()

Dès qu’une propriété publique est mise à jour (via wire:model ou par une méthode qui modifie $this->xxx), Livewire peut appeler :

  • updated($propertyName) : avec le nom de la propriété qui vient d’être mise à jour (ex. 'search', 'status'). Utile pour réagir de façon générique.
  • updatedXxx() : méthode dédiée à la propriété $xxx (ex. updatedSearch(), updatedStatus()). Plus lisible quand vous ne ciblez qu’un ou deux champs.

Exemple typique : réinitialiser la pagination quand l’utilisateur change la recherche ou un filtre, pour ne pas rester sur une page vide.

use Livewire\WithPagination;

class ArticleList extends Component
{
use WithPagination;
public string $search = '';

public function updatedSearch(): void
{
$this->resetPage();
}

public function render() { ... }
}

Dès que $search change (saisie ou blur selon wire:model), updatedSearch() est appelé et resetPage() remet la page à 1. Le prochain render() utilisera la nouvelle valeur de $search et la page 1.

Autre exemple : logger ou envoyer un événement quand un filtre change.

public function updatedStatus(): void
{
$this->dispatch('filters-changed');
}

hydrate() et dehydrate()

Ces hooks sont plus avancés. Ils sont appelés autour de la sérialisation de l’état du composant :

  • dehydrate() : appelé après que Livewire a préparé l’état à envoyer au client (juste avant d’envoyer la réponse). Vous pouvez retirer des données sensibles ou lourdes de l’état, ou ajouter des métadonnées.
  • hydrate() : appelé après que Livewire a restauré les propriétés publiques à partir de la requête entrante (avant d’exécuter la méthode d’action). Vous pouvez reconstruire des objets non sérialisables (ex. recréer un modèle Eloquent à partir d’un ID stocké dans une propriété).

Cas d’usage : vous stockez un ID dans une propriété publique (léger, sérialisable) et vous ne voulez pas sérialiser tout le modèle Eloquent (qui peut être lourd ou contenir des relations). Dans hydrate(), vous rechargez le modèle à partir de l’ID ; dans dehydrate(), vous pouvez vous assurer de ne pas envoyer l’objet entier au client (en le remplaçant par null ou en ne l’exposant pas comme propriété publique).

Exemple simplifié :

public ?int $postId = null;
protected ?Post $post = null;

public function mount(int $postId): void
{
$this->postId = $postId;
$this->post = Post::findOrFail($postId);
}

public function hydrate(): void
{
if ($this->postId) {
$this->post = Post::find($this->postId);
}
}

public function dehydrate(): void
{
// Ne pas sérialiser $post ; il sera recréé dans hydrate()
$this->post = null;
}

En pratique, Livewire gère déjà bien les modèles Eloquent (sérialisation par ID) ; hydrate/dehydrate servent surtout pour des cas custom (objets métier non Eloquent, nettoyage, cache).


Approfondissement

  • Ordre d’exécution (résumé) : requête reçue → désérialisation des propriétés → hydrate() → mise à jour des propriétés (wire:model) → updated()* pour chaque propriété modifiée → méthode d’action (ex. save) → render()dehydrate() → sérialisation → réponse envoyée. Connaître cet ordre évite de mettre dans updated() une logique qui dépend d’une propriété pas encore à jour.
  • Éviter de sérialiser des objets lourds : si vous stockez un modèle Eloquent avec des relations chargées, le payload peut grossir. Dans dehydrate(), vous pouvez remplacer $this->post par null (ou ne garder que $this->postId) ; dans hydrate(), vous rechargez $this->post = Post::find($this->postId). Ainsi seul l’ID est sérialisé.
  • mount() vs hydrate() : mount() n’est appelé qu’une fois (premier rendu). hydrate() est appelé à chaque requête après désérialisation. Utilisez mount() pour les paramètres passés par la vue et le chargement initial ; hydrate() pour recréer des objets non sérialisables à chaque tour.

À retenir

  • mount() : appelé une fois à la création ; idéal pour paramètres (ex. ID) et chargement initial (ex. Post::findOrFail($postId)). updated($property) / updatedPropertyName() : après chaque mise à jour d’une propriété ; utiliser pour resetPage(), dispatch d’événements. hydrate() / dehydrate() : autour de la sérialisation ; cas avancés (objets lourds, sécurité).
  • resetPage() dans updatedSearch() (ou équivalent) pour les listes paginées ; authorize() dans mount() pour les pages réservées (module 9).

Dans le prochain module, nous voyons l’architecture : traits réutilisables, composants full-page et layouts dédiés pour structurer des applications Livewire plus grandes.