Skip to content
Layers
Esc
navigateopen⌘Jpreview
On this page

Lifecycle

Phase, transition, and actionStatus — the three independent axes of layer state.

Confusing exiting for a phase is the most common mental-model mistake — it’s a transition value. Layer state actually spans three independent axes: phase (resolution), transition (animation), and actionStatus (in-layer mutations).

State flow

Serial scope adds queued: later opens wait behind the occupying layer and are not in getSnapshot() — use getQueuedSnapshot() to observe them.

The three axes

phase: "pending" | "queued" | "active" | "dismissed" | "error"; // resolution
transition: "entering" | "settled" | "exiting"; // animation
actionStatus: "idle" | "running"; // in-flight action

Phase — resolution lifecycle

Phase Meaning
pending loadFn in flight (cancelable via AbortController).
queued Serial scope only: waiting behind the occupying layer; not in getSnapshot(); visible via getQueuedSnapshot().
active Mounted; component receives call, payload, data, error, phase, transition, actionStatus, dismissing.
dismissed Caller’s await resolved (ended=true); layer may still be mounted while transition: "exiting".
error loadFn threw; the caller’s await rejects.

After dismissal, the layer is removed from the stack snapshot. If gcTime > 0 and the layer had data !== undefined, it is cached off-snapshot so re-opening the same keyThe logical identity of a layer; find/upsert/gcTime operate on its signature. can restore data without re-running loadFn.

Transition — animation axis

"exiting" is not a phase member. Enter/exit animation lives on transition. phase: "dismissed" means the promise resolved; transition disambiguates exit animation vs cached:

moment phase transition
opening, loading pending entering
opening, no load active entering
open & idle active settled
dismissed, animating out dismissed exiting
dismissed, cached (gcTime) dismissed settled
load threw error settled

Completion is whichever fires first of { delay elapsed, call.settle() }:

  • enteringDelay — ms before entering → settled (default 0 = instant).
  • exitingDelay — ms before removal after dismiss (default 0 = instant).
  • call.settle() — imperative early finish: entering → settled (clears enter timer; phase untouched); exiting → remove (clears exit timer); no-op if already settled.

Delay 0 (default) flips the axis synchronously — no transition frame observed. For fixed CSS transitions, set enteringDelay/exitingDelay and skip settle(). For springs or variable duration, use a generous cap delay and onTransitionEnd/onRest → call.settle().

Action status — in-layer mutations

actionStatus (idle | running) tracks async work inside a layer — for example a submit button calling call.setRunning(true) during a mutation. It is orthogonal to both phase and transition.

Last updated on July 19, 2026

Was this page helpful?