Framework-agnostic state management library designed for simplicity and scalability

Simple primitives

xoid is based on atoms. Atoms are holders of state. create function is used to create them.

It has a Recoil-inspired API for derived atoms.

import { create } from 'xoid'
const atom = create(3)
console.log(atom.value) // 3
atom.set(5)
atom.update(state => state + 1)
console.log(atom.value) // 6
const derivedAtom = create(get => get(atom) * 2)

Actions

With the second argument, you can specify actions for your atoms.

import { create } from 'xoid'
const counterAtom = create(3, (atom) => ({
increment: () => atom.update((s) => s + 1),
incrementBy: (by) => atom.update((s) => s + by)
}))
counterAtom.actions.incrementBy(5)
setInterval(counterAtom.actions.increment, 1000)

React integration

xoid has a minimal React integration. No need for wrapping components into context providers. Just import useAtom and start using!

import { create } from 'xoid'
import { useAtom } from '@xoid/react'
// in a React component
const count = useAtom(counterAtom)
const { increment } = counterAtom.actions
// outside React
const unsubscribe = alpha.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 { create } from 'xoid'
const atom = create({ 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!

No additional syntax is required to define and use finite state machines. Just use the second argument of the callback as the state transition function.

import { create } from 'xoid'
const red = { color: '#f00', onClick: () => machine.set(green) }
const green = { color: '#0f0', onClick: () => machine.set(red) }
const machine = create(red)
// in a React 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