Skip to content

Commit 37bfb1e

Browse files
committed
more work on prefixReducer
1 parent fbcc733 commit 37bfb1e

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,32 @@ Creates a middleware that delegates to a hot-swappable middleware. The returned
5959
`replaceMiddleware(nextMiddleware: Middleware)` function. This way you can use Webpack hot reloading on
6060
your custom middleware.
6161

62+
## prefixReducer(prefix: string): (reducer: Reducer) => Reducer
63+
```js
64+
import {prefixReducer} from 'mindfront-redux-utils';
65+
```
66+
67+
A reducer decorator that strips `prefix` from each `action.type` before passing it to the decorated `reducer`.
68+
If the `action.type` doesn't start with `prefix`, it will just return the `state` instead of calling `reducer`.
69+
70+
If the decorated reducer has `actionHandlers` (from `createReducer`), then the returned reducer will have
71+
`actionHandlers` with the prefixed action type keys.
72+
73+
### Example
74+
import {combineReducers} from 'redux'
75+
import {createReducer, prefixReducer} from 'mindfront-redux-utils'
76+
77+
const counterReducer = createReducer(0, {
78+
DECREMENT: state => state - 1,
79+
INCREMENT: state => state + 1,
80+
})
81+
82+
const reducer = combineReducers({
83+
counter1: prefixReducer('COUNTER_1.')(counterReducer),
84+
counter2: prefixReducer('COUNTER_2.')(counterReducer),
85+
})
86+
87+
reducer({}, {type: 'COUNTER_1.INCREMENT'}) // {counter1: 1}
88+
reducer({counter1: 3, counter2: 3}, {type: 'COUNTER_1.DECREMENT'}) // {counter1: 2, counter2: 3}
89+
reducer({counter1: 3, counter2: 3}, {type: 'COUNTER_2.INCREMENT'}) // {counter1: 3, counter2: 4}
90+

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"lodash.compact": "^3.0.1",
8585
"lodash.every": "^4.6.0",
8686
"lodash.foreach": "^4.5.0",
87+
"lodash.mapkeys": "^4.6.0",
8788
"lodash.mapvalues": "^4.6.0",
8889
"lodash.memoize": "^4.1.2",
8990
"lodash.reduce": "^4.6.0",

src/prefixReducer.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1+
import mapKeys from 'lodash.mapkeys'
2+
import createReducer from './createReducer'
3+
14
export default function prefixReducerActionTypes(prefix) {
2-
return reducer => (state, action) => action.type.startsWith(prefix)
3-
? reducer(state, {...action, type: action.type.substring(prefix.length)})
4-
: state
5+
return reducer => {
6+
if (reducer.actionHandlers instanceof Object) {
7+
return createReducer(reducer.initialState, mapKeys(reducer.actionHandlers, (handler, key) => prefix + key))
8+
}
9+
return (state, action) => action.type.startsWith(prefix)
10+
? reducer(state, {...action, type: action.type.substring(prefix.length)})
11+
: state
12+
}
513
}
614

test/prefixReducer.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
import {expect} from 'chai'
2+
import createReducer from '../src/createReducer'
23
import prefixReducer from '../src/prefixReducer'
34

45
describe('prefixReducer', () => {
5-
const reducer = (state, action) => action.type === 'INCREMENT' ? state + 1 : state
6-
7-
it('works', () => {
6+
it('works for basic reducer', () => {
7+
const reducer = (state, action) => action.type === 'INCREMENT' ? state + 1 : state
8+
const reducer2 = prefixReducer('TEST.')(reducer)
9+
expect(reducer2(1, {type: 'INCREMENT'})).to.equal(1)
10+
expect(reducer2(1, {type: 'TEST.INCREMENT'})).to.equal(2)
11+
expect(reducer2(1, {type: 'BLAH.INCREMENT'})).to.equal(1)
12+
})
13+
it('works for action map reducer', () => {
14+
const reducer = createReducer(0, {
15+
INCREMENT: state => state + 1,
16+
DECREMENT: state => state - 1,
17+
})
818
const reducer2 = prefixReducer('TEST.')(reducer)
19+
expect(reducer2.initialState).to.equal(0)
20+
expect(reducer2.actionHandlers['TEST.INCREMENT']).to.be.an.instanceof(Function)
21+
expect(reducer2.actionHandlers['TEST.DECREMENT']).to.be.an.instanceof(Function)
922
expect(reducer2(1, {type: 'INCREMENT'})).to.equal(1)
1023
expect(reducer2(1, {type: 'TEST.INCREMENT'})).to.equal(2)
1124
expect(reducer2(1, {type: 'BLAH.INCREMENT'})).to.equal(1)
25+
expect(reducer2(1, {type: 'DECREMENT'})).to.equal(1)
26+
expect(reducer2(1, {type: 'TEST.DECREMENT'})).to.equal(0)
27+
expect(reducer2(1, {type: 'BLAH.DECREMENT'})).to.equal(1)
1228
})
1329
})
1430

0 commit comments

Comments
 (0)