An efficient reducer exploiting ES6 Map for better lookup!
npm i typed-redux-kit.mapped-reducer
# Or install typed-redux-kit
npm i typed-redux-kit
import { createStore } from 'redux'
import { MappedReducer } from 'typed-redux-kit.mapped-reducer'
import {
PureAction,
PayloadAction,
} from 'typed-redux-kit.base'
enum ActionTypes {
Plus = 'test_Plus',
Set = 'test_Set',
}
namespace Actions {
export interface Plus extends PureAction<ActionTypes.Plus> {}
export interface Set extends PayloadAction<ActionTypes.Set, {
count: number
}> {}
}
interface State {
count: number
}
const plusReducer = (state: State, action: Actions.PlusAction) => ({
...state,
count: state.count + 1,
})
const setReducer = (state: State, action: Actions.SetAction) => ({
...state,
...action.payload,
})
const combinedReducer = new MappedReducer<State>({
initialState: {
count: 0,
},
})
combinedReducer
.set(ActionTypes.Plus, plusReducer)
.set(ActionTypes.Set, setReducer)
const store = createStore(combinedReducer.reduce)
store.dispatch({
type: ActionTypes.Plus,
} as Actions.Plus)
If you want to set multiple reducers for one action, Try MappedPipeReducer
.
import { MappedPipeReducer } from 'typed-redux-kit.mapped-reducer'
const combinedReducer = new MappedPipeReducer<State>({
initialState: {
count: 0,
},
})
combinedReducer
.set(ActionTypes.Plus, plusReducer)
.set(ActionTypes.Set, setReducer)
.set([
ActionTypes.Plus,
ActionTypes.Set,
], anotherReducer)
Now, the both actions will be passed to anotherReducer
And for more convinence, it accepts string enum!
combinedReducer
.set(ActionTypes.Plus, plusReducer)
.set(ActionTypes.Set, setReducer)
.set(ActionTypes, anotherReducer)
combinedReducer
will pass all actions to every one of its subreducers. When you build a huge app, you probably have lots of reducers, split by domain. Sometimes you want to share actions and this was developed to solve that problem. Even with reducers split by domain, actions can be passed to multiple reducers.
Also, if you have lots of action types, a lookup with Map is more efficient than one with a switch
statement. This is because Map keeps a key as a hash.
Basic mapped reducer. It takes only one option, initialState
.
Set a subreducer for the given action type(s).
It takes a single action type and array/string enum of action types.
You can set only one subreducer for a single action type. If you want to set more than two, use
MappedPipeReducer
.
Delete a subreducer for the given action type(s).
Get a subreducer for the given action type(s).
This is the actual reducing method. You should pass this to createStore
or combineReducers
.
import {
createStore,
combineReducers,
} from 'redux'
// To store
const store = createStore(reducer.reduce)
// To combine reducer
const masterReducer = combineReducers({
slave1: reducer.reduce,
slave22: reducer2.reduce,
})
MappedPipeReducer can have multiple subreducers for a given action type(s).
Prepends a subreducer to a subreducer array of a given action type(s).
Alias of #unshift
Appends a subreducer to a subreducer array of a given action type(s).
Alias of #push
Replaces a subreducer array of a given action type(s).
Deletes all subreducers registered of a given action type(s).
Almost the same as MappedReducer#get
, but returns an array of reducers.
Same as MappedReducer#reduce
.
MappedReducer is using Object.values. If you need to support legacy Node.js or browser, use the polyfill below or transpile it again with babel
// Polyfill
const reduce = Function.bind.call(Function.call, Array.prototype.reduce)
const isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable)
const concat = Function.bind.call(Function.call, Array.prototype.concat)
const keys = Reflect.ownKeys
if (!Object.values) {
Object.values = function values<T extends {}, K extends keyof T>(O: T) {
return reduce(keys(O), (v: T[K], k: K) => concat(v, typeof k === 'string' && isEnumerable(O, k) ? [O[k]] : []), [])
}
}
- Stuart Schechter
- Junyoung Choi : Maintainer
- Joseph Stein
Licensed under MIT Copyright 2017 Revisolution