type-to-reducer
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -1,14 +0,18 @@ | ||
interface reducerMapFunction { | ||
(state: any, action: any): any | ||
interface reducerMapFunction<S, A> { | ||
(state: S, action?: A): S; | ||
} | ||
interface reducerMap { | ||
[key: string]: reducerMap | reducerMapFunction | ||
interface reducerMapReturnFunction<S, A> { | ||
(state: S | undefined, action?: A): S; | ||
} | ||
interface reducerMap<S, A> { | ||
[key: string]: reducerMap<S, A> | reducerMapFunction<S, A>; | ||
} | ||
declare module 'type-to-reducer' { | ||
export default function typeToReducer ( | ||
reducerMap: reducerMap, | ||
initialState: any | ||
): reducerMapFunction | ||
export default function typeToReducer<S, A = any>( | ||
reducerMap: reducerMap<S, A>, | ||
initialState: S, | ||
): reducerMapReturnFunction<S, A>; | ||
} |
@@ -13,4 +13,6 @@ 'use strict'; | ||
// internal state | ||
var typeDelimiter = '_'; | ||
// change the string separating action types when reducerMap is nested | ||
var setTypeDelimiter = exports.setTypeDelimiter = function setTypeDelimiter(customTypeDelimiter) { | ||
@@ -20,19 +22,21 @@ return typeDelimiter = customTypeDelimiter; | ||
function typeToReducer(reducerMap, initialState) { | ||
var makeType = function makeType(prefix, type) { | ||
return prefix.concat(type).join(typeDelimiter); | ||
}; | ||
// function to concatenate any nested types | ||
var _makeType = function _makeType(prefix, type) { | ||
return prefix.concat(type).join(typeDelimiter); | ||
}; | ||
var iterator = function iterator(reducers) { | ||
var initial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; | ||
// iterator function that will read the reducerMap and return a flattened object | ||
var _flattenReducerMap = function _flattenReducerMap(reducers) { | ||
var initial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; | ||
var reducerTypes = Object.keys(reducers || {}); | ||
return reducerTypes.reduce(function (acc, type) { | ||
var reducer = reducers[type]; | ||
return typeof reducer === 'function' ? _extends({}, acc, _defineProperty({}, makeType(prefix, type), reducer)) : iterator(reducer, acc, [makeType(prefix, type)]); | ||
}, initial); | ||
}; | ||
var reducerTypes = Object.keys(reducers || {}); | ||
return reducerTypes.reduce(function (acc, type) { | ||
var reducer = reducers[type]; | ||
return typeof reducer === 'function' ? _extends({}, acc, _defineProperty({}, _makeType(prefix, type), reducer)) : _flattenReducerMap(reducer, acc, [_makeType(prefix, type)]); | ||
}, initial); | ||
}; | ||
var flattened = iterator(reducerMap); | ||
function typeToReducer(reducerMap, initialState) { | ||
var flattened = _flattenReducerMap(reducerMap); | ||
@@ -39,0 +43,0 @@ return function () { |
{ | ||
"name": "type-to-reducer", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Create reducer functions based on an object keyed by action types", | ||
@@ -8,3 +8,3 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"test": "mocha test/index.test.js --ui bdd --compilers js:babel-register", | ||
"test": "mocha test/index.test.js --ui bdd --require babel-register", | ||
"lint": "eslint . --ext .js", | ||
@@ -39,5 +39,5 @@ "build": "babel src -d lib --ignore *.test.js && cp -f src/index.d.ts lib/index.d.ts", | ||
"pre-push": "^0.1.1", | ||
"sinon": "^4.0.2", | ||
"sinon-chai": "^2.13.0" | ||
"sinon": "^7.4.1", | ||
"sinon-chai": "^3.0.0" | ||
} | ||
} |
@@ -7,10 +7,8 @@ [![Circle CI](https://circleci.com/gh/tomatau/type-to-reducer/tree/master.svg?style=svg)](https://circleci.com/gh/tomatau/type-to-reducer/tree/master) | ||
Create reducer functions based on an object keyed by action types | ||
This module provides a function `typeToReducer`, which accepts an object (`reducerMap`) and returns a reducer function composing other reducer functions described by the `reducerMap`. | ||
## Why? | ||
Pretty much the same as the `handleActions` function in https://github.com/acdlite/redux-actions | ||
This is pretty much the same as the `handleActions` function you can find in https://github.com/acdlite/redux-actions. The differences being, `type-to-reducer` only exposes the function as a default, and allows nesting of the `reducerMap` object. | ||
Differences being that this only exposes the one function and allows nesting - API suggested by https://github.com/pburtchaell/redux-promise-middleware/issues/35#issuecomment-164650859 | ||
## Usage | ||
@@ -20,2 +18,10 @@ | ||
The `reducerMap` you supply to the function will have keys that correspond to dispatched action types and the values for those keys will be reducer functions. When the returned reducer function is called with state and an action object, the action's type will be matched against the previously provided `reducerMap` keys, if a match is found, the key's value (the reducer function) will be invoked with the store's state and the action. | ||
Also, you can describe an initial state with the second argument to `typeToReducer`. | ||
Oh and you can also set `reducerMap`s as the values too, these objects will be nested instances of the same shaped object you supplied to `typeToReducer`. | ||
If that sounded a bit complicated, the example below should make it clearer. NB, it helps if you're familiar with redux. | ||
```js | ||
@@ -31,3 +37,5 @@ import typeToReducer from 'type-to-reducer' | ||
export const reducer = typeToReducer({ | ||
// supply the reducerMap object | ||
export const myReducer = typeToReducer({ | ||
// e.g. GET === 'SOME_ACTION_TYPE_STRING_FOR_GET' | ||
[GET]: (state, action) => ({ | ||
@@ -44,5 +52,18 @@ ...state, | ||
Can also be used to group reducers by prefix. | ||
Then the `myReducer` would be used like so: | ||
```js | ||
let state = { foo: 'bar' } | ||
let newState = myReducer(state, { | ||
type: GET, | ||
payload: `an action's payload.` | ||
}) | ||
// newState will deep equal { foo: 'bar', data: `an action's payload.` } | ||
``` | ||
Group reducers by a prefix when objects are nested. | ||
```js | ||
import typeToReducer from 'type-to-reducer' | ||
@@ -57,3 +78,3 @@ import { API_FETCH } from 'app/actions/bar' | ||
export const reducer = typeToReducer({ | ||
export const myReducer = typeToReducer({ | ||
[ API_FETCH ]: { | ||
@@ -74,2 +95,11 @@ PENDING: () => ({ | ||
}, initialState) | ||
// usage | ||
let previousState = Whatever; | ||
let newState = myReducer(previousState, { | ||
type: API_FETCH + '_' + PENDING, | ||
}) | ||
// newState shallow deeply equals { isPending: true } | ||
``` | ||
@@ -94,3 +124,3 @@ | ||
export const reducer = typeToReducer({ | ||
export const myReducer = typeToReducer({ | ||
[ API_FETCH ]: { | ||
@@ -105,7 +135,5 @@ PENDING: () => ({ | ||
// Then use the delimiter in your action type | ||
reducer(someState, { | ||
type: API_FETCH + '@_@' + 'PENDING' | ||
myReducer(someState, { | ||
type: API_FETCH + '@_@' + PENDING, | ||
}) | ||
``` | ||
This function may change to something that will scale better such as `setOptions(options)` to support more settings if more pop up. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13207
157
132