Using reducers

xoid doesn't need reducers, but if you prefer to use them, or if you're moving away from Redux, but want to reuse your existing reducers, you can easily do that with xoid.

The following xoid model can be used to setup a Redux-like behavior in an atom.

const StoreModel = (reducer, state) =>
create(state, (atom) => (action) => atom((s) => reducer(s, action)))

In the second argument, a dispatch function is built.

Let's take this simple reducer:

const types = { increase: "INCREASE", decrease: "DECREASE" }
const counterReducer = (state, { type, by }) => {
switch (type) {
case types.increase: return {
count: state.count + by
case types.decrease: return {
count: state.count - by


import { use, subscribe } from 'xoid'
const store = StoreModel({ count: 0 }, counterReducer)
const dispatch = use(store)
dispatch({ type: types.increase, by: 1 })

Connecting existing reducers to xoid can be beneficial, especially if you're planning to gradually refactor your reducers. The above reducer can be simplified into to the following:

const CounterModel = (state) => create(state, (atom) => {
const $count = use(atom, 'count')
return {
increment: (by) => $count(s => s + by),
decrement: (by) => $count(s => s - by),

To see another demonstration with a more dramatic refactor, you can check Working with nested state

Related: Using in an existing Redux App

Last updated on