createReactiveActionStore

function createReactiveActionStore<TArgs, TResult>(
    fn,
): ReactiveActionStore<TArgs, TResult>;

Wraps an async function in a ReactiveActionStore. Each dispatch creates a fresh AbortController and aborts the previous one; the superseded call's outcome is dropped, so only the most recent dispatch can mutate state.

The wrapped function receives the AbortSignal as its first argument, followed by whatever arguments were passed to dispatch. Callers attach their own cancellation source per-call via ReactiveActionStore.withSignalstore.withSignal(signal).dispatch(...). The caller's signal is composed with the per-dispatch controller via AbortSignal.any, so aborting it cancels the in-flight call and surfaces the abort reason on state.

Type Parameters

Type ParameterDescription
TArgs extends readonly unknown[]Argument tuple forwarded from dispatch to fn.
TResultResolved value type of fn.

Parameters

ParameterTypeDescription
fn(signal, ...args) => Promise<TResult>Async function to wrap. Receives an AbortSignal plus the dispatch arguments.

Returns

ReactiveActionStore<TArgs, TResult>

A ReactiveActionStore exposing dispatch, dispatchAsync, getState, subscribe, reset, and withSignal.

Example

const store = createReactiveActionStore(async (signal, accountId: Address) => {
    const response = await fetch(`/api/accounts/${accountId}`, { signal });
    return response.json();
});
 
store.subscribe(() => console.log(store.getState()));
store.dispatch(someAccountId); // fire-and-forget; state is the source of truth
 
// Per-attempt timeout — fresh signal per call:
store.withSignal(AbortSignal.timeout(30_000)).dispatch(someAccountId);
 
// Imperative call with the resolved value:
const account = await store.dispatchAsync(someAccountId);

See

ReactiveActionStore

On this page