Less boilerplate when create a new reducer on Redux
Method:
'use strict'
const createReducer = (initialState, actionHandlers) => {
return (state = initialState, action) => {
return actionHandlers.hasOwnProperty(action.type)
? actionHandlers[action.type](state, action)
: state
}
}
export default createReducer
Usage:
'use strict'
import { ADD_COUNTER, REMOVE_COUNTER, INCREMENT, DECREMENT } from './actions'
import createReducer from '../create-reducer'
export const initialState = []
export default createReducer(initialState, {
[ADD_COUNTER]: (state, action) => state.concat(0),
[REMOVE_COUNTER]: (state, action) => state.filter((_, i) => i !== action.index),
[INCREMENT]: (state, action) => state.map((c, i) => i === action.index ? c + 1 : c),
[DECREMENT]: (state, action) => state.map((c, i) => i === action.index ? c - 1 : c)
})
Remove duplication on
INCREMENT
andDECREMENT
methods:What is duplicated?
What is different on duplicated methods?
INCREMENT -> c + 1
DECREMENT -> c - 1
Let's use composition! First, create functions for increment and decrement, just with the different parts:
Nice! The only thing that was different is isolated! Now, let's create a method to isolate the duplication. This method will receive one of the above functions - to increment or decrement - by argument, and return a new function - the same that was passed to
map
methods above.Before return this function, we need to return another function, to receive the selected index (
action.index
).After that, instead of use
c + 1
orc - 1
, we can use the functioninc
ordec
, passed by argument, and pass to this function thec
value to it do what it must do:Now, it's time to use
exec
onmap
functions to remove duplication:With this signature, we may create two another methods for increment or decrement on map:
Then, pass those methods for
map
functions:The final code:
You can still improving this code, removing duplication of
state.map
. Just create a new function to execute theincrement
ordecrement
method (different parts):And use it:
The final code: