Skip to main content

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 the state of a focused branch, changes will propagate to the root.

import { atom } 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 that 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! 🎉