Skip to content

Which primitive should I use?

There are five primitives. They share the same shape — a name, a configuration, optional insertions — and differ only in where the value comes from and what triggers it.

The decision

Where does the value live?Use
In memory, you own itstate
On a server, readquery
On a server, writtenmutation
In the URL's query stringqueryParams
Nowhere — it's an action with a lifecycleasyncProcess

The same table, by symptom

"I need a value the user can change."state. It is the default. Reach for anything else only when the value's home is somewhere other than memory.

"I need to display data from an API."query. It re-runs when its params change and carries isLoading / status / exception for you. Don't put a query result into a state — that's two sources of truth.

"I need to send something to an API."mutation. Triggered explicitly with .mutate(...). Connect it back to the read side with insertReactOnMutation rather than reloading by hand.

"This filter should survive a refresh and be shareable."queryParams. The URL becomes the source of truth; your query's params read from it.

"I need to run an async thing and know if it's running."asyncProcess. Use it for operations that are not a server read or write: a file export, a share sheet, a delay, a Web API call.

Things that are not a primitive

  • Derived values — use Angular's computed inside an insertion. Craft doesn't replace signal derivation, it hosts it.
  • Reusable logic across primitives — that's an insertion, not a primitive.
  • A group of primitives with a name and a scope — that's a craftService.

What they have in common

Whichever you pick, the mechanics are identical: the name comes first, the result is the primitive reference itself, yield* drives it inside any craft generator, and the last argument is an insertion.

That shared shape is one page: Anatomy of a primitive. Read it once and every primitive page becomes just its own specifics.

See Also