skip to content

In Livewire 4, when do you use interceptors such as $wire.intercept() or Livewire.interceptRequest() rather than Livewire.hook(), for example to handle 419 responses?

level: seniorimportance: should knowfreq 22%

answer

  1. action, message and request levels
  2. scoped to one component or action
  3. onError with preventDefault
  4. commit and request hooks deprecated
  5. Livewire.on returns an unsubscribe

basics

~20 s

Livewire 4 interceptors wrap network traffic at three levels, action, message and request, with onSend, onSuccess, onError and onFinish callbacks; Livewire.hook() remains for component, element and morph lifecycle events. A global request interceptor handles 419s.

solid answer

~40 s

Livewire 4 splits client extension points in two. **Interceptors** wrap traffic: `$wire.intercept()` per action (optionally one named action), `interceptMessage()` per component message, and `interceptRequest()` per HTTP request, each available on `$wire` or globally on `Livewire`. Their callbacks, `onSend`, `onSuccess`, `onError`, `onFailure` for network errors and `onFinish`, can cancel work, and `onError` can call `preventDefault()` to replace Livewire's default handling: a "page has expired" confirm for 419, an error modal otherwise. So a global `Livewire.interceptRequest()` that checks `response.status === 419` and offers a reload is the idiomatic session-expiry handler. `Livewire.hook()` is for lifecycle events such as `component.init`, `element.init` and the `morph.*` family; its old `commit` and `request` hooks still work but are deprecated in favour of interceptors. `Livewire.on()` listens for dispatched events and returns an unsubscribe function.

go deeper

for a junior

Know that Livewire lets JavaScript run code around its requests, and that a global handler can catch an expired-session 419.

for a middle

Explain the three interceptor levels, scoping to a component or one action, and the onError versus onFailure split.

for a senior

Migrate v3 commit and request hooks to interceptors, centralise status handling, and prevent listener leaks under wire:navigate.

for a principal

Define which client concerns, such as telemetry, auth expiry and error UX, are handled globally, and how teams add interceptors without conflicts.

## Two kinds of client extension point Livewire's JavaScript exposes two families of callbacks, and Livewire 4 draws a clear line between them. - **Interceptors** wrap the **network round trip**: when an action is sent, when a response arrives, when it fails. - **Hooks**, registered with `Livewire.hook(name, callback)`, fire on **lifecycle events** of the page: a component initialising, an element initialising, the DOM morph adding, updating or removing nodes. Livewire 3 used hooks for both. Its `commit` and `request` hooks still run in Livewire 4 for backwards compatibility, but the upgrade guide marks them deprecated and maps them to `interceptMessage` and `interceptRequest`. ## The three interceptor levels | Level | Fires | Registered with | Typical use | |---|---|---|---| | **Action** | once per method call | `$wire.intercept(cb)`, `$wire.intercept('save', cb)`, `Livewire.interceptAction(cb)` | confirm, toast, per-action loading state | | **Message** | once per component update | `$wire.interceptMessage(cb)`, `Livewire.interceptMessage(cb)` | react after state sync or morph | | **Request** | once per HTTP request, which may batch several components | `$wire.interceptRequest(cb)`, `Livewire.interceptRequest(cb)` | status-code handling, redirects, telemetry | Each callback receives registration functions for its phases. The common ones are `onSend`, `onCancel`, `onSuccess`, `onError` (the server answered with an error), `onFailure` (a network error) and `onFinish`, which runs after the DOM morph or after an error or cancel. Message interceptors add finer phases such as `onSync`, `onMorphed` and `onRender`; request interceptors add `onResponse`, `onRedirect` and `onDump`. Action and message interceptors can cancel: `action.cancel()` or `cancel()`. Every registration **returns an unsubscribe function**, and component-scoped interceptors registered from a component's script are cleaned up when the component is removed. ## Handling expired sessions globally When a session expires, the CSRF check answers the next update with **419**; in production Livewire's own tamper guards, such as a checksum mismatch or a locked-property write, also answer with a bare 419. By default Livewire's client reacts to a 419 with a browser `confirm()` saying the page has expired and offering a reload, and to other errors with an error modal. A single global request interceptor lets you replace that with your own experience, such as saving a draft first: ```javascript Livewire.interceptRequest(({ onError }) => { onError(({ response, preventDefault }) => { if (response.status !== 419) return preventDefault() if (confirm('Your session expired. Reload the page?')) window.location.reload() }) }) ``` Register it in a `livewire:init` listener, or in your own bundle before `Livewire.start()`, so it exists before the first request. ## Timing within one message Message interceptors expose the order in which a successful response is applied, which matters when your code needs the new DOM: 1. `onSuccess`, right after the response arrives; 2. `onSync`, after the snapshot's state is merged; 3. `onEffect`, after effects such as dispatched events are processed; 4. `onMorph`, during the DOM morph, for advanced async work Livewire must wait for; 5. `onMorphed`, after every morph for the response is done; 6. `onFinish`, after that, when the action's promise also resolves; 7. `onRender`, in the next animation frame. Code that measures or focuses new elements belongs in `onMorphed` or later; code that only needs the data can run in `onSync`. ## Where `Livewire.hook()` still fits 1. `component.init` runs when Livewire discovers a component, on first load or later, and provides a `cleanup` callback. 2. `element.init` runs for each element inside a component, which is a way to implement custom attributes. 3. `morph.updating`, `morph.updated`, `morph.removing`, `morph.removed`, `morph.adding` and `morph.added` run per element during the morph, plus `morph` and `morphed` per component, for integrations that must react to DOM patches. ## Events are separate: `Livewire.on` `Livewire.on('booking-confirmed', ({ id }) => ...)` listens for events dispatched from PHP or JavaScript, and `Livewire.dispatch()` sends them. `Livewire.on()` returns a function that removes the listener. With `wire:navigate`, an Alpine component's `init()` may run again on each visit, so store those functions and call them in the Alpine `destroy()` method, or listeners pile up. ## Choosing quickly - A confirm dialog before `delete`: action interceptor scoped to `'delete'`. - A spinner on one booking form: `$wire.intercept` with `onSend` and `onFinish`. - Global 419 or 500 handling: `Livewire.interceptRequest`. - A third-party library that must re-scan the DOM after patches: a `morph.*` hook. - React to a domain event from anywhere: `Livewire.on`.

  • What is the difference between onError and onFailure in a Livewire 4 interceptor?
    `onError` fires when the server responded with an error status such as 419 or 500; it receives the response and a `preventDefault()` that skips Livewire's default handling, the page-expired confirm or the error modal. `onFailure` fires when the request never got a usable response, a network error, and receives the error object. Handling both covers session expiry and offline users separately.
  • Why can Livewire.on listeners multiply on a site that uses wire:navigate?
    `wire:navigate` swaps pages without a full reload, so an Alpine component's `init()` that registers `Livewire.on(...)` can run again on every visit while the old listeners stay registered. `Livewire.on()` returns an unsubscribe function; keep them and call them in the Alpine component's `destroy()` method.

saying these in an interview costs you the question

  • Livewire 4 removed the commit and request hooks entirely.
  • Interceptors can only be registered globally on the Livewire object.
  • onFailure is where you handle a 419 response.
  • Livewire.hook('request') is the recommended v4 way to catch errors.
  • Livewire.on listeners are always cleaned up automatically on navigation.