In a Livewire component, which lifecycle hooks run only on the first render, which only on later requests, and which on every request?
answer
- the object is rebuilt every request
- boot and booted: always
- hydrate: later requests only
- dehydrate runs before the snapshot
- hydrateFoo per public property
basics
~10 smount() runs only on the first render; hydrate() and hydrateFoo() run only on later requests; boot(), booted(), dehydrate() and dehydrateFoo() run on every request, and rendering()/rendered() whenever the view renders.
solid answer
~30 sLivewire rebuilds the component object on **every** request, so hooks are split by request type. The first render runs `boot()`, then `mount()`, then `booted()`. A later request restores public properties from the signed snapshot, then runs `boot()`, `hydrate()`, a `hydrateFoo($value)` for each public property, and `booted()`. Both kinds then render (`rendering()`/`rendered()`) and finish with `dehydrate()` and a `dehydrateFoo($value)` per property, just before the new snapshot is taken. That is why `boot()` is the place to re-create **protected** state, which is never in the snapshot, and why `hydrate()` suits code that must only run when state came back from the browser.
go deeper
Remember the split: mount once, hydrate only on later requests, boot and dehydrate every time.
Explain the snapshot round trip and why protected state must be rebuilt in boot() while public state is restored automatically.
Watch per-request cost: boot() and hydrate() run on every interaction, so queries there multiply with every keystroke a live input sends.
Set a team rule for where derived and non-serialisable state lives, so components stay cheap to rebuild on each request.
## Why Livewire needs more than a constructor A **Livewire component** is not kept alive on the server between interactions. Each interaction is a new HTTP request that carries a **snapshot**: the component's public property values, metadata and a checksum. Livewire verifies the checksum, builds a **new** instance of the class, writes the public properties back onto it, runs the request, then serialises the state into a fresh snapshot for the browser. Turning PHP state into that JSON is **dehydration**; turning it back into a PHP object is **hydration**. Because the object is rebuilt each time, `__construct()` is not a place for setup: Livewire documents that components use `mount()` for one-time initialisation instead. Every other hook exists to let code run at a specific point of that rebuild cycle. ## The two request shapes | Hook | First render | Later request | |---|---|---| | `boot()` | yes, before `mount()` | yes, before `hydrate()` | | `mount()` | yes | no | | `hydrate()` | no | yes | | `hydrateFoo($value)` | no | yes, once per public property | | `booted()` | yes, after `mount()` | yes, after `hydrate()` | | `updating*` / `updated*` | no | only when updates arrive | | `rendering()` / `rendered()` | yes | yes, unless rendering is skipped | | `dehydrate()` | yes | yes | | `dehydrateFoo($value)` | yes, once per public property | yes, once per public property | `Foo` stands for the StudlyCase property name: a public `$lineItems` gets `hydrateLineItems($value)` and `dehydrateLineItems($value)`. ## What each hook is for - **`boot()`** runs at the start of every request. On a later request the public properties have already been restored when it runs; on the first render they still hold their declared defaults because `mount()` has not run yet. Its classic job is re-creating **protected or private properties**, which Livewire never puts in the snapshot and therefore loses between requests. - **`booted()`** runs after `mount()` or `hydrate()`, so it sees the component's real state on both request types. - **`hydrate()`** runs only when a component came back from the browser. Use it for work that makes no sense on the first render, such as turning a plain array from the snapshot back into a richer object. - **`dehydrate()`** runs at the end of every request, after rendering and just before the snapshot is taken, so it can convert state back into something Livewire can serialise. - **`hydrateFoo()` / `dehydrateFoo()`** do the same for one property and receive its value. ## A worked example on an order form An order form keeps its lines in `public array $lines` and a protected `TaxCalculator` service. The calculator is not serialisable and is not public, so it vanishes after the first request. Setting it in `boot()` restores it every time; setting it in `mount()` would work once and then leave a `null` on the next click. ## Common mistakes 1. Initialising protected state in `mount()` and being surprised it is gone on the next request. 2. Expecting `hydrate()` on the first render; it only runs when a snapshot is restored. 3. Changing a property in `dehydrate()` and expecting the HTML to show it: the view has already rendered, although the change is written into the snapshot. 4. Doing heavy queries in `boot()` or `hydrate()`, which multiplies their cost by every interaction. Livewire's own documentation recommends **Wireables or Synthesizers** over hand-written `hydrate()`/`dehydrate()` pairs for custom types, and a computed property over a `boot()`-loaded value for most derived data. ## Choosing the right hook When deciding where a piece of setup code belongs, ask two questions: does it need to run on every request, and does it need the restored state? | Need | Hook | |---|---| | once, with parameters from the page | `mount()` | | every request, state not needed | `boot()` | | every request, state needed | `booted()` | | only when coming back from the browser | `hydrate()` | | convert state before it is serialised | `dehydrate()` | This table is also a good way to answer the interview question aloud: name the split, then give one concrete job for each hook, such as rebuilding a protected service in `boot()` or converting a value object back to an array in `dehydrate()`.
- On a later request, do public properties already hold the browser's values when boot() runs?Yes. Livewire verifies the snapshot and writes the public properties onto the new instance before it calls `boot()`. Incoming updates from that request have not been applied yet; they are written after `booted()`. On the first render `boot()` sees only declared defaults, because `mount()` has not run.
- Why does a protected property set in mount() become null on the next click?Only public properties go into the snapshot. The next request builds a fresh object, restores the public ones, and never calls `mount()` again, so the protected property is back to its default. Assign it in `boot()`, or derive it on demand.
- If dehydrate() changes a public property, where does that change show up?In the snapshot sent back to the browser, not in the HTML of the current response: `dehydrate()` runs after the view has rendered and before the snapshot is taken. The change becomes visible in the markup on the next render.
A Livewire component is like a hotel room turned over for each stay: the guest's suitcase (public properties) travels with them, but the minibar (protected properties) has to be restocked by housekeeping (boot) every single check-in.
saying these in an interview costs you the question
- Believes Livewire keeps the component object alive in server memory between requests.
- Puts one-time setup in __construct() of a Livewire component.
- Thinks hydrate() runs on the first render as well.
- Expects protected properties to survive between requests like public ones.
- Claims dehydrate() runs only on later requests.