reduceur
v2.0.1
Published
> _Sophisticated reducers_
Downloads
3
Readme
reduceur 🥖
Sophisticated reducers
reduceur
makes it hassle-free to create type-safe state reducers. No unweildy switch
-statements and TypeScript boilerplate. Just define your event handlers and you're ready!
Additionally, reduceur
comes with Immer's produce
API baked in, allowing you to write even more compact event handlers.
- 🥖 Simple
- 🥖 Great TS support
- 🥖 Uses Immer
- 🥖 Framework agnostic
- 🥖 Inspired by XState's
createModel
and Redux Toolkit'screateSlice
APIs
Quick Start
npm i reduceur immer
import { createReducer, State } from "reduceur";
type CounterState = {
count: number;
};
const counterReducer = createReducer((state: State<CounterState>) => ({
incremented: () => {
state.count++;
},
decremented: () => {
state.count--;
},
changed: (payload: { count: number }) => {
state.count = payload.count;
},
}));
const initialState = { count: 0 };
const nextState = counterReducer(initialState, { type: "changed", count: 999 });
Event Creators
The reducer returned from createReducer
comes with built-in event creators:
import { createReducer, State } from "reduceur";
type CounterState = {
count: number;
};
const counterReducer = createReducer((state: State<CounterState>) => ({
changed: (payload: { newCount: number }) => (state.count = payload.newCount),
}));
const initialState = { count: 0 };
const nextState = counterReducer(
initialState,
// event names are prefixed with `create`
counterReducer.createChanged({ newCount: 1000 })
);
Note that these are event creators, which means that invoking them only returns a compatible event object; it does not send any events to the reducer.
connect
A connect
method is available on the returned reducer, which, by providing a function with which events can be sent to your store, allows you to create an object with event senders.
A contrived example with React's useReducer
:
import { createReducer, State } from "reduceur";
const counterReducer = createReducer((state: State<CounterState>) => ({
incremented: () => state.count++,
changed: (payload: { newCount: number }) => (state.count = payload.newCount),
}));
const Counter = () => {
const [state, send] = useReducer(counterReducer, { count: 0 });
// event names are prefixed with `send`
const { sendIncremented, sendChanged } = counterReducer.connect(send);
return (
<>
<button onClick={sendIncremented}>Increment</button>
<button onClick={() => sendChanged({ newCount: 100 })}>Set to 100</button>
</>
);
};