useAsync
Overview
useAsync manages an abort signal, status, result, and error for one task while protecting state from stale completions.
Signature
type AsyncTask<T> = (signal: AbortSignal) => Promise<T> | T;
function useAsync<T>(
task: AsyncTask<T>,
options?: { immediate?: boolean; onError?: (error: unknown) => void },
): {
status: 'idle' | 'pending' | 'success' | 'error';
data: T | undefined;
error: unknown;
run: () => Promise<T>;
cancel: () => void;
reset: () => void;
};Parameters
task receives a new AbortSignal for each run. immediate defaults to false and starts a run after commit when true. onError observes the error from the latest non-cancelled run.
Returns
State plus stable run, cancel, and reset actions. run preserves the task's resolved value and rejection.
Behavior
A new run aborts the prior controller. Sequence checks prevent older results from updating state. cancel keeps data and sets status to idle; reset also clears data and error. A current task failure sets status to error, calls onError when provided, and keeps the original promise rejection. Cancelled or stale runs do not report errors.
SSR / RSC
SSR starts in idle state. Even immediate work starts only in a client effect. Use the Hook in a Client Component.
Example
Composition
Debounce an input value before changing the task, or cancel it when an associated disclosure closes.