Easy & TypeSafe & Immutable reducer(No Redux Dependency)
npm i -S fluent-reducer immer example for react
npm i -S react export interface IRootState { name: string } const RootState: IRootState = { name: 'unknown' } // 'root' is unique ID import { ReactFluentReduer } from 'fluent-reducer/react' // for not react app // import { FluentReduer } from 'fluent-reducer' export const rootReducer = new ReactFluentReducer<'root', IRootState>(RootState, { verbose: true, middlewares: [(state, action) => { // this state can edit. not plane object, so if you save state like localstorage, use subscribe console.log(state, action) }] }) export const changeName = rootReducer.sync<string>('CHANGE_NAME', (state, name) => { state.name = name }) const asyncChangeState = reducer.async<string, string, Error>('ASYNC_CHANGE_NAME', (name, dispatch, getState) => { return new Promise(resolve => { setTimeout(() => { resolve(name) }, 3000) }) }, { // before promise action started(state, params) { console.log('started', params) state.state = 'started' }, // promise rejected action failed(state, { error }) { console.error(error) }, // promise resolved action done(state, { result }) { state.name = result console.log('done') } }) export const MyExample: React.FC = () => { const [state, dispatch] = rootReducer.useFluentReducer() const _handleOnClick = useCallback(() => { // execute changeName action dispatch(changeName(Date.now().toString())) }, [dispatch]) return ( <div onClick={_handleOnClick}>{state.name}</div> ) } rootReducer.subscribe((state, action) => { // this state is readonly. if you want to update state, use middlewares option. console.log(state, action) })