onSettled
Schedules callback to run once after the reactive graph has fully
settled — i.e. Once every pending async read inside the current owner has
resolved and the queue has flushed. Each call registers a single fire; it
does not create an ongoing subscription.
The canonical lifecycle primitive in 2.0. Three main usages:
- Component-level setup-and-teardown (the most common shape): run
setup after the component's first stable render and return a cleanup
function to dispose it on owner disposal. This is the replacement for
the 1.x
onMount+onCleanuppairing — setup and teardown live in one block, andonCleanupis no longer the right tool for component bodies. (onMountno longer exists in 2.0.) - Post-settle "ready" hook: run once after a component's first stable render — analytics ping, focus, scroll-into-view, etc. No cleanup needed.
- Inside an event handler: schedule work to run after the action / transition triggered by the event has completed.
Reactive reads inside the callback are not tracked — to react to
subsequent settles, register a new onSettled each time.
onCleanup is not allowed inside the callback — return a cleanup
function instead. The returned cleanup runs on owner disposal.
A cleanup return is only honored when onSettled is called from an owned
scope (e.g. A component body). When it fires out of band from an unowned
scope — an event handler, a tracked effect, or another onSettled — there is
no owner lifecycle to bind a cleanup to; returning one is a dev-mode error
(and is dropped in production). Use the post-settle/event-handler forms below
for one-shot work, and keep setup-with-teardown in an owned scope.
Import
import { onSettled } from "solid-js";Type signature
function onSettled(callback: () => void | (() => void)): void;Parameters
callback
Function to run; may return a cleanup function that fires on owner disposal
Examples
// Component-level setup + teardown — replaces onMount + onCleanup.// Subscribe to an external source on mount, unsubscribe on dispose.function useViewportWidth() { const [width, setWidth] = createSignal(window.innerWidth); onSettled(() => { const onResize = () => setWidth(window.innerWidth); window.addEventListener("resize", onResize); return () => window.removeEventListener("resize", onResize); }); return width;}// Post-settle "ready" hook — no cleanup needed.function Dashboard() { const data = createMemo(async () => fetchData());
onSettled(() => { analytics.track("dashboard.ready"); });
return ( <Loading fallback={<Spinner />}> <pre>{data()}</pre> </Loading> );}// Event-handler — runs after the action settles.function SaveButton() { const save = action(function* () { yield api.save(); });
const handleClick = () => { save(); onSettled(() => toast("Saved!")); };
return <button onClick={handleClick}>Save</button>;}