Framework-agnostic state management library designed for simplicity and scalability
Small
It's easy-to-learn, has no external dependencies, and it's only 1.1kB minified and gzipped.
Robust
It's based on immutable updates and explicit subscriptions. This makes it ideal for teams.
Well-documented
Extensively documented, including a rich "Recipes" section and examples.
Simple primitives
xoid is based on atoms. Atoms are holders of state. atom
function is used to create them.
import { atom } from 'xoid'
const $count = atom(3)
$count.set(5)
$count.update((state) => state + 1)
console.log($count.value) // 6
Actions
With the second argument, you can define actions for your atoms.
import { atom } from 'xoid'
const $count = atom(3, (atom) => ({
increment: () => atom.update((s) => s + 1),
incrementBy: (by) => atom.update((s) => s + by)
}))
$count.actions.incrementBy(5)
Computed Values
It has a Recoil-inspired API for derived atoms. Alternatively, the .map
method can be used.
import { atom } from 'xoid'
const $doubleCount = atom((get) => get($count) * 2)
const $tripleCount = $count.map((state) => state * 3)
Framework Integrations
xoid has React, Vue, and Svelte integrations. It can be used without any framework as well.
import { atom } from 'xoid'
import { useAtom } from '@xoid/react'
// @xoid/vue and @xoid/svelte packages are used the same way
// in a component
const count = useAtom($count)
const { increment } = $count.actions
// vanilla JavaScript
const unsubscribe = $count.subscribe(console.log)
No more hand-written reducers!
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 { 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.update((s) => s + 1)
// root state is replaced with new immutable state
assert($atom.value !== previousValue) // ✅
No-API Finite State Machines!
Atoms are potent primitives. No additional syntax is required for expressing finite state machines.
import { atom } from 'xoid'
const red = { color: '#f00', onClick: () => machine.set(green) }
const green = { color: '#0f0', onClick: () => machine.set(red) }
const $machine = atom(red)
// in a component
const { color, onClick } = useAtom($machine)
return <div style={{ color }} onClick={onClick}/>
- Easy to learn
- Small bundle size
- Zero configuration
- Framework-agnostic
- Computed values
- Async actions
- Transient updates
- Local & global state
- Finite state machines
- Extensive Typescript support
- Devtools