[]previous and next page

Updating a store

Updating a store in the State with useStore guide.

For agentsUpdated

setStore accepts these forms. Every call is one batched transaction: readers of everything that changed are notified once, and the call itself is untracked.

Form Meaning
setStore({ title: "x" }) Merges the keys into the object. For an array store, an array replaces the contents (diffed, see reconcile).
setStore((draft) => { draft.title = "x"; }) Draft: mutate freely (assign, push, splice, delete). Returning a value instead merges it (objects) or reconciles it (arrays).
setStore("user", "name", "x") Path: up to four steps, then a value. Fully type-checked; deeper or dynamic paths go through a draft.
setStore("count", (n) => n + 1) Path ending in an updater (previous) => next.
setStore("todos", 2, { done: true }) Path ending in a partial object: merged into the existing object. Arrays and primitives replace.
setStore(reconcile(next)) Diffs next into the store; retained items keep their identity.
setStore("todos", reconcile(next)) The same, for one sub-tree only.
setStore(produce((draft) => { ... })) produce returns its argument; it exists for code migrated from other libraries.

Rules of the draft#

  • A draft is valid only while the update function runs. Keeping it and writing later throws a TypeError ("a draft was used after its setStore() call returned").
  • Reads through a draft are not tracked.
  • Writing a value equal to the current one (Object.is) notifies nothing.
  • Assign fresh data (draft.items = [...] with new objects) or change arrays in place (push, splice, sort, index assignment). Do not assign an array that was built from draft items with filter, map or slice: those items are drafts and are not valid after the update. To keep a filtered subset, use setStore("items", reconcile(state.items.filter(...))); reconcile unwraps store items.
  • Path steps and merged keys named __proto__, constructor or prototype throw a TypeError.

Errors#

Store errors are TypeErrors with a ShadowStore prefix. A path that goes through a value that is not an object, a path step that does not fit the container (a string on an array), and setStore() with no argument all throw. A write to the read-only view throws as well: