skip to content

In Livewire 4, what does wrapping part of a component in @island change about re-rendering, and when would you still use a child component instead?

level: seniorimportance: should knowfreq 20%

answer

  1. one region re-renders on its own
  2. @island(name:, lazy:, defer:)
  3. wire:island scopes an action
  4. the whole component still hydrates
  5. parallel requests: last response wins

basics

~10 s

An @island region re-renders independently: an action inside it, or one scoped with wire:island, re-renders only that region, and a normal component re-render skips it; state and hydration still belong to the whole component.

solid answer

~40 s

`@island ... @endisland` marks a region of one component's Blade view that Livewire can render on its own. An action triggered inside the island, or from elsewhere with `wire:island="name"`, re-renders only that region, and a normal re-render of the component **skips** islands unless they use `always: true`. `@island(lazy: true)` or `defer: true` also delays the island's first render, with an `@placeholder`. What islands do not change: the request still carries and hydrates the whole component's state, runs its hooks and action, and islands share that state, so parallel island requests can overwrite each other and the last response wins. Islands cannot sit inside `@foreach` or `@if` and cannot see template variables from outside. Choose a **child component** when a region needs its own state, lifecycle, or separate reuse.

code

html · 15 lines
html
<div>
    <x-kpi-strip :totals="$this->totals" />

    @island(name: 'revenue', defer: true)
        @placeholder
            <div class="h-64 animate-pulse"></div>
        @endplaceholder

        <canvas data-series='@json($this->revenueSeries)'></canvas>
    @endisland

    <button wire:click="$refresh" wire:island="revenue">
        Refresh chart
    </button>
</div>

go deeper

for a junior

Recall that @island marks a region that can re-render on its own inside one component.

for a middle

Explain wire:island targeting, lazy and defer islands, and that component re-renders skip islands by default.

for a senior

Separate render isolation from state isolation, and watch for last-response-wins races between parallel island requests.

for a principal

Decide when a team should reach for islands versus splitting components, based on state ownership rather than render cost alone.

## The problem islands solve A Livewire component re-renders its **whole** Blade view after every action. On a sales dashboard component that holds a heavy revenue chart, a KPI strip and a filter bar, refreshing the chart re-renders everything, including every computed query the other sections call. Before Livewire 4, the usual fix was to split the chart into a **child component**, with props, events and a second lifecycle. **Islands**, new in Livewire 4, give the same render isolation inside one component. ## How an island behaves - `@island ... @endisland` marks a region. On the first page load it renders with the rest of the view. - An action fired **inside** the island (for example a `wire:click="$refresh"` button in it) re-renders **only** that island. - An action elsewhere can target it with `wire:island="revenue"` next to `wire:click`, or from JavaScript with `$wire.$island('revenue')`. - When the component itself re-renders, islands are **skipped** by default; `@island(always: true)` opts a region into every render. - `@island(lazy: true)` delays the first render until the island is visible; `defer: true` loads it right after page load; `skip: true` shows only its `@placeholder` until something triggers it. - Named islands with the same name render together; `wire:island.append` and `.prepend` add content instead of replacing it, which suits "load more" feeds. ## What islands do not isolate | Concern | With an island | With a child component | |---|---|---| | HTML re-rendered | only the island | only the child | | State sent and hydrated | the whole parent component | only the child's state | | Hooks and action run | the parent's | the child's | | Own props and lifecycle | no | yes | | Can live in a loop | no | yes, with keys | So an island saves **render** work and DOM morphing, but not the cost of hydrating the full component. A computed property referenced only inside the island is evaluated only when the island renders, which is where much of the saving comes from on a dashboard. ## Rules and traps 1. **No loops or conditionals around an island.** `@island` cannot be placed inside `@foreach` or `@if`; put the loop or condition inside it. 2. **No outside template variables.** Variables from `@php` blocks or enclosing loops are not visible inside the island; use component properties or computed properties. 3. **Shared state races.** Island requests can run in parallel with each other and with the root. They all mutate the same component state, so when two are in flight the **last response wins** for that state. 4. **Nesting.** An outer island's re-render skips inner islands unless they use `always: true`. ## Choosing between them Use an island when the region is part of one component's state and you only want to stop re-rendering unrelated markup, such as a chart panel refreshed by its own button. Use a child component when the region has state of its own, needs its own authorisation or lifecycle, must appear in a list, or is reused across pages. Interviewers look for the distinction between **render isolation** (islands) and **state isolation** (child components). ## A dashboard walk-through A dashboard component holds `$range`, a KPI strip, a revenue chart and an activity feed. Without islands, clicking **Refresh chart** re-runs every computed query in the view. With the chart inside `@island(name: 'revenue', defer: true)`: 1. the first page load renders the KPI strip and feed, with a skeleton where the chart goes; 2. right after load, the island renders in its own request; 3. **Refresh chart** with `wire:island="revenue"` re-renders only the chart; 4. changing `$range` re-renders the component but skips the island, unless it is marked `always: true`, so a chart that depends on the range must be marked that way or refreshed explicitly. That last step is the design question interviewers push on: islands make stale regions possible by design, so each island must declare how it stays in sync.

  • Why can two island refreshes fired close together show inconsistent data?
    Island requests can run in parallel, but each one carries and returns the whole component's state. If both change the same property, whichever response arrives last overwrites the snapshot the browser keeps, so one island may reflect state the other has already replaced.
  • Why does a computed property used only inside an island help performance?
    Computed properties are evaluated when the view reads them. If only the island reads it, a render that skips the island never runs the query. A plain public property assigned in a hook would be computed on every request regardless.

saying these in an interview costs you the question

  • Believes an island sends and hydrates only its own slice of state.
  • Wraps @island inside a @foreach to get one island per row.
  • Expects a normal component re-render to update every island.
  • Assumes island requests are serialised, so state conflicts cannot happen.