Overview
atom is the foundational reactive unit in Mates. It is a plain callable function object — calling it reads the value and registers a reactive dependency so the enclosing template, memo, or effect re-runs whenever the value changes.
Create atoms in the component outer function (or at module level for app-wide state). Read them with count(), count.get(), or count.val — all three are equivalent reactive reads. Write with .set() (value or updater) or .update() for in-place object/array mutation.
Passing a function to atom() creates a derived atom. The function runs immediately; any atoms read inside become dependencies, and the derived value recomputes whenever they change. Derived atoms can chain.
Same-value writes still notify. Unlike some frameworks, count.set(count()) is treated as a change and re-runs subscribers. Use a silent write (set(v, true)) when you must mutate without notifying.
atom vs nearby APIs
|
API
|
Mutability
|
Prefer when
|
|---|---|---|
atom
| Mutable + notify | Default for reactive values and small objects. |
iAtom / signal
| Deep-frozen on set | Configs / read-models where in-place mutation should fail. |
memo(fn)
| Derived only |
Same runner as atom(() => …); clearer “computed” intent.
|
asyncAtom
| Async data + status | Keyed fetch/refetch with loading/error — not a plain value cell. |
Creating and reading atoms
Atoms are reactive variables. Read them in the template with atom() — any template that reads an atom will re-render when it changes.
Derived atoms
Pass a function to atom() to create a computed value that auto-recomputes when its dependencies change.
In-place update for objects
profile.update(draft => …) mutates the live object/array and notifies. Prefer this for nested field edits; use set() to replace the whole value.
Lock and unlock writes
While locked, set/update are blocked. Unlock with the same passcode to write again.