reducer-pipe
v1.0.1
Published
Allows to pipe redux reducers with given state and action, passing previously returned state to next reducer, then keep last updated state.
Downloads
38
Maintainers
Readme
reducer-pipe
reducer-pipe
helps you to pipe redux
reducers with given state and action, passing previously returned state to next reducer, then keep last updated state.
Getting started
Install reducer-pipe
using npm:
npm install reducer-pipe --save
Then using ES6
import { increment, decrement } from './my-reducers';
import reducerPipe from 'reducer-pipe';
export default reducerPipe([
increment,
decrement,
]);
Using ES5
var myReducers = require('./my-reducers');
var reducerPipe = require('reducer-pipe');
module.exports = reducerPipe([
myReducers.increment,
myReducers.decrement,
]);
Usage
You can rewrite this:
const reducer = (state, action) => {
if (!state) state = initialState;
switch (action.type) {
case 'ADD':
case 'INCREMENT':
return incrementReducer(state, action);
case 'SUBTRACT':
case 'DECREMENT':
return decrementReducer(state, action);
default:
return state;
}
};
reducer({counter: 0}, {type: 'INCREMENT'}); //=> {counter: 1}
To this:
import reducerPipe from 'reducer-pipe';
const reducer = reducerPipe([
(state/*, action*/) => (state ? state : initialState),
incrementReducer,
decrementReducer,
]);
reducer({counter: 0}, {type: 'INCREMENT'}); //=> {counter: 1}
See also
reducer-chain
in order to chain given reducers with same given state and action.
Examples
Explanation
Take this code:
const reducer = reducerPipe([
initial, // returns initial state if given state is null, else returns given state
increment, // increments counter in state copy if action is INCREMENT, else returns given state
decrement, // decrements counter in state copy if action is DECREMENT, else returns given state
]);
When we call:
reducer(null, {type: 'INCREMENT'}); // default compare set to `reducerPipe.compare.withInitial`
It will execute:
// We pass given state and action to our first reducer in list, which is `initial`
initial(null, {type: 'INCREMENT'}) //=> returns initial state {counter: 0}
compare(null, {counter: 0}) //=> Previous state is null, returns {counter: 0}
// now we will pass previously returned state by compare
increment({counter: 0}, {type: 'INCREMENT'}) //=> Increment counter by 1, returns {counter: 1}
compare({counter: 0}, {counter: 1}) //=> Current state differs from previous, returns {counter: 1}
// now we will pass previously returned state by compare
decrement({counter: 1}, {type: 'INCREMENT'}) //=> Nothing happens, returns given state {counter: 1}
compare({counter: 1}, {counter: 1}) //=> Both state are the same object, returns {counter: 1}
Pipe:
reducer(state, action) => updatedState
initial(state, action) => newState
compare(state, newState) => newState
increment(newState, action) => updatedState
compare(newState, updatedState) => updatedState
decrement(updatedState, action) => updatedState
compare(updatedState, updatedState) => updatedState
Chain:
reducer(state, action) => updatedState
initial(state, action) => newState
increment(state, action) => updatedState
decrement(state, action) => state
compare(state, newState) => newState
compare(newState, updatedState) => updatedState
compare(updatedState, state) => updatedState
Compare signature
initialize(initialState) => iterator(previousState, currentState) => nextState
initialState
is corresponding to the state passed to the high order reducer.previousState
is corresponding to the previously returned state. Defaults toinitialState
.currentState
is corresponding to the state returned by the reducer at the current index in the list.nextState
is corresponding to the state you want to keep.initialize
will be called everytime once with the given state from the high order reducer. It must returns an iterator function for comparing previous and current state, and return the prefered one.iterator
will be called on each reducer result (passed ascurrentState
). It must compare withpreviousState
(defaults toinitialState
) and return the state you want to keep next.
Note: Please note that initiaze
is called before calling any reducer.
Then reducer are called one by one in given order, and iterator
is called after each reducer
.
Available compare functions
reducer-pipe
built in with 4 different compare functions available under reducerPipe.compare
:
| Name | Signature | Equals |
| ---- | --------- | ------ |
| withInitial
(default) | (initialState) => (previousState, currentState) => nextState
| R.equals(initialState, currentState)
|
| withInitialCustomEquals
| (customEquals) => (initialState) => (previousState, currentState) => nextState
| customEquals(initialState, currentState)
|
| withPrevious
| (initialState) => (previousState, currentState) => nextState
| R.equals(previousState, currentState)
|
| withPreviousCustomEquals
| (customEquals) => (initialState) => (previousState, currentState) => nextState
| customEquals(previousState, currentState)
|
Compare usage
With immutable
:
// ./immutableReducerPipe.js
import Immutable from 'immutable';
import reducerPipe from 'reducer-pipe';
export default reducerPipe(
reducerPipe.compare.withPreviousCustomEquals(Immutable.is)
);
// ./index.js
import Immutable from 'immutable';
import { reducer1, reducer2 } from './reducers';
import immutableReducerPipe from './immutableReducerPipe';
const initialState = Immutable.Map({counter: 0});
export default immutableReducerPipe([
(state/*, action*/) => (state ? state : initialState),
reducer1,
reducer2,
]);
With custom compare:
import reducerPipe from 'reducer-pipe';
import {reducer1, reducer2} from './reducers';
const customCompare = initialState => (previousState, currentState) => (
currentState !== null &&
currentState !== initialState ?
currentState : previousState
);
const initialState = Object.freeze({counter: 0});
export default reducerPipe(customCompare, [
(state/*, action*/) => (state ? state : initialState),
reducer1,
reducer2,
]);
Links
renum
is a small library to create enum using frozen objects in javascript from multiple sources.reducer-chain
helps you to chainredux
reducers with given state and action, then keep last updated state.reducer-sandbox
helps you to reuse your reducers in different place without conflict them.