Using reducers
You can easily use your existing reducers with xoid. The following function can be used to create an atom with reducer.
const atomWithReducer = (reducer, initialState) => atom(
initialState,
(a) => ({ dispatch: (action) => a.update((s) => reducer(s, action)) })
)
Let's take this simple reducer:
const types = { increase: "INCREASE", decrease: "DECREASE" }
const counterReducer = (state, { type, by }) => {
switch (type) {
case types.increase: return {
...state,
count: state.count + by
}
case types.decrease: return {
...state,
count: state.count - by
}
}
}
Usage:
const countAtom = atomWithReducer({ count: 0 }, counterReducer)
countAtom.actions.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 = (s) => atom(s, (a) => {
const $count = a.focus('count')
return {
increment: (by) => $count.update(s => s + by),
decrement: (by) => $count.update(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