Async state

Every operation exposes one immutable snapshot:

type AsyncState<Data, Empty = null> = {
  status: "idle" | "loading" | "success" | "error";
  data: Data | Empty;
  error: unknown | null;
  isLoading: boolean;
};

The fields are deliberately separate. A request can keep useful data while reporting an error, and isLoading can remain true while another concurrent request completes.

Lifecycle

EventstatuserrorisLoading
Created or resetidlenullfalse
Executeloadingnulltrue
ResolvesuccessnullDepends on active requests
RejecterrorRejection valueDepends on active requests
Abortidlenullfalse

By default, failures preserve the previous data. Use dataOnError when a failure should replace it:

const operation = createAsync(loadItems, {
  initialData: [],
  dataOnError: () => [],
});

Immutable snapshots

Snapshots are frozen and replaced as a unit. Consumers can safely compare snapshot references, while adapters can expose each field through their native reactive APIs.