In a Livewire update request, in what order do boot, hydrate, booted, the update hooks, the called action, rendering, rendered and dehydrate run, and which bugs does that order explain?
answer
- snapshot restored before boot
- boot, hydrate, booted
- all writes, then all updated hooks
- action after the updated hooks
- render, then dehydrate, then snapshot
basics
~20 sLivewire restores public state, then runs boot(), hydrate() and hydrateFoo(), booted(), the updating hooks as values are written, all updated hooks, the called actions, rendering()/rendered() around the view, and finally dehydrate() before taking the new snapshot.
solid answer
~40 sOn an update request Livewire verifies the snapshot checksum and restores public properties, then calls `boot()`, `hydrate()`, a `hydrateFoo()` per property and `booted()`. Next it applies the incoming updates: each `updating*` hook runs as its value is written, and **all** `updated*` hooks run after every write. Then it calls the requested actions, renders with `rendering()` before and `rendered()` after the view, and ends with `dehydrate()` and `dehydrateFoo()` before the new snapshot. That order explains real bugs: an action runs after the `updated*` hooks and can overwrite their result; a value set in `rendered()` or `dehydrate()` misses this response's HTML; `booted()` is the first hook that sees the component's real state on both request types; and an `updated*` hook sees sibling fields changed in the same request.
go deeper
Recall the broad order: restore state, boot and hydrate, apply updates, run the action, render, dehydrate.
Explain that updated hooks run after all writes and before actions, and that render hooks bracket the view.
Use the order to diagnose one-click-late UI, actions clobbering hook results and costly per-request queries in boot or hydrate.
Encourage one recalculation path per derived value so hook order cannot produce inconsistent totals across a large component library.
## The pipeline, step by step A **Livewire update request** carries three things: the component's signed **snapshot**, a set of **updates** (property paths with new values) and a list of **calls** (actions to run). The server handles them in a fixed order: 1. **Restore.** Livewire checks the snapshot checksum, creates a new instance of the class and writes the public properties back onto it. 2. **`boot()`** and its trait-suffixed versions, then the trait hooks named `initialize` plus the trait name. 3. **`hydrate()`**, then one **`hydrateFoo($value)`** per public property. 4. **`booted()`**. 5. **Updates.** For each incoming path: `updating($path, $value)` and the property-level `updating*` hook, then the write. The matching `updated*` hooks are collected and run only **after every update in the request has been written**. 6. **Actions.** Each requested method runs in turn. 7. **Render.** `rendering($view, $data)`, the Blade view, then `rendered($view, $html)`. 8. **`dehydrate()`**, then one **`dehydrateFoo($value)`** per public property. 9. **Snapshot.** The new state is serialised and signed for the browser. The first render differs only at the start: `mount()` takes the place of `hydrate()` and the `hydrateFoo()` calls, and there are no updates or calls. ## Bugs the order explains | Symptom | Cause in the order | |---|---| | An action "resets" a total that the user just edited | the action runs after `updated*` and overwrites its result | | A flag set in `rendered()` does not appear on screen | the HTML is already produced; the flag lands in the snapshot | | `boot()` reads `$this->orderId` as the default on first load | on the first render `boot()` runs before `mount()` | | An `updated*` hook sees the new discount code sent alongside the quantity | all writes happen before any `updated*` hook | | Rejecting input in `updated*` is too late | the value is already written; use `updating*` | ## Using the order on an order form Say a quantity input and an **Apply coupon** button are submitted together. The quantity update is written first, `updatedItems()` recalculates the subtotal, and only then does `applyCoupon()` run, so the coupon sees the new subtotal. If instead the discount were computed in `updatedItems()` and the coupon action recomputed the subtotal from stale data, the user would see a total that disagrees with the lines. Putting the recalculation in one method that both call keeps the result consistent. ## Hooks that do not always run - **Render hooks** do not fire when rendering is skipped for the request. - **Update hooks** fire only when the request carries updates. - **`exception()`** fires only when a hook or action throws. ## Performance consequences Everything in steps 2 to 4 runs on **every** interaction, before Livewire even knows what the user did. A query in `boot()` or `hydrate()` therefore costs one round trip to the database per click or per sent keystroke. Prefer loading data lazily in the action or view that needs it, or in a cached computed value, and keep the per-request hooks to cheap restoration work. ## Clients cannot jump the queue The browser cannot call a lifecycle hook as an action: Livewire blocks method names such as `mount`, `boot`, `booted`, `hydrate*`, `dehydrate*`, `updating*`, `updated*`, `rendering`, `rendered` and `exception`, including trait-suffixed boot and mount hooks, with `DirectlyCallingLifecycleHooksNotAllowedException`. So the order above is the only order in which they run. ## How to answer in an interview A strong answer walks the pipeline once, then turns it into diagnosis: "the value was one click late because it was set in `rendered()`", "the action overwrote what `updatedItems()` computed", "the query ran on every keystroke because it lived in `hydrate()`". Interviewers at senior level are less interested in reciting nine steps than in hearing that the candidate has used the order to find a real bug, and knows which hook to move the code into to fix it.
- Why is booted() often a safer place than boot() for code that reads component state?`booted()` runs after `mount()` on the first render and after `hydrate()` on later requests, so on both paths the component's real state is in place. `boot()` on the first render runs before `mount()`, when properties still hold declared defaults.
- A property changed in rendered() shows up one click late. Why, and how do you fix it?`rendered()` runs after the HTML is produced, so the change only reaches the snapshot and appears on the next render. Move the logic to an `updated*` hook, the action, or `rendering()` so it runs before the view renders.
- What happens if the browser sends a call to hydrate or updatedQuantity as an action?Livewire refuses it with `DirectlyCallingLifecycleHooksNotAllowedException`. Lifecycle methods, including trait-suffixed boot and mount hooks, are on a protected list, so a user cannot trigger them out of order.
saying these in an interview costs you the question
- Says the called action runs before the property updates are applied.
- Believes each updated hook runs immediately after its own property is written.
- Expects a property changed in rendered() to show in the same response.
- Thinks boot() sees mount() values on the first render.
- Assumes the browser may call hooks such as hydrate() as actions.