Quick Tutorial
You can skip this part if you've already read the Github README.
Atom
Atoms are holders of state.
import { atom } from 'xoid'
const $count = atom(3)
console.log($count.value) // 3
$count.set(5)
$count.update((state) => state + 1)
console.log($count.value) // 6
Atoms can have actions.
import { atom } from 'xoid'
const $count = atom(5, (a) => ({
increment: () => a.update(s => s + 1),
decrement: () => a.value-- // `.value` setter is supported too
}))
$count.actions.increment()
There's the .focus
method, which can be used as a selector/lens. xoid is based on immutable updates, so if you "surgically" set state of a focused branch, changes will propagate to the root.
import create from 'xoid'
const $atom = atom({ deeply: { nested: { alpha: 5 } } })
const previousValue = $atom.value
// select `.deeply.nested.alpha`
const $alpha = $atom.focus(s => s.deeply.nested.alpha)
$alpha.set(6)
// root state is replaced with new immutable state
assert($atom.value !== previousValue) // ✅
assert($atom.value.deeply.nested.alpha === 6) // ✅
Derived state
State can be derived from other atoms. This API was heavily inspired by Recoil.
const $alpha = atom(3)
const $beta = atom(5)
// derived atom
const $sum = atom((read) => read($alpha) + read($beta))
Alternatively, .map
method can be used to quickly derive the state from a single atom.
const $alpha = atom(3)
// derived atom
const $doubleAlpha = $alpha.map((s) => s * 2)
Atoms are lazily evaluated. This means that the callback functions of
$sum
and$doubleAlpha
in this example won't execute until the first subscription to these atoms. This is a performance optimization.
Subscriptions
For subscriptions, subscribe
and watch
are used. They are the same, except watch
runs the callback immediately, while subscribe
waits for the first update after subscription.
const unsub = $atom.subscribe((state, previousState) => {
console.log(state, previousState)
})
// later
unsub()
This concludes the basic usage! 🎉