redux-fun
v1.3.7
Published
Redux functional programming utilities
Downloads
15
Maintainers
Readme
redux-fun :wrench:
Redux functional programming utilities
Install
$ npm install --save redux-fun
Documentation
Reducers
Compose reducers
const { composeReducers, pipeReducers } = require('redux-fun');
const reducer_1 = composeReducers(r3, r2, r1);
const reducer_2 = pipeReducers(r1, r2, r3);
Convert updaters
const { toReducer } = require('redux-fun');
const updater = (action) => state => state;
const reducer = toReducer(updater);
Updaters
updater with initial state
const { withDefaultState } = require('redux-fun');
// normal
const updater_1 = withDefaultState({}, action => state => state);
// curried
const updater_2 = withDefaultState({})(action => state => state);
Middlewares
Compose middlewares
const { composeMiddlewares, pipeMiddlewares } = require('redux-fun');
const middleware_1 = composeMiddlewares(m3, m2, m1);
const middleware_2 = pipeMiddlewares(m1, m2, m3);
Preserve async flow (deprecated)
Use preserveAsyncSeries instead
Preserve async series
Respect the dispatch order with async middleware
const { preserveAsyncSeries } = require('redux-fun');
const middleware_1 = preserveAsyncSeries('ACTION_TYPE')
const middleware_2 = preserveAsyncSeries(['ACTION_TYPE_1', 'ACTION_TYPE_2'])
Handlers
A Handler from the handle-io library can be tranformed into redux middleware using createHandleIOMiddleware function.
Redux Handlers
A redux handler
run every time an action was dispatched.
It takes two arguments:
- action
- reduxHandleIOApi
The reduxHandleIOApi object provides 3 IOs functions :
- getState
- dispatch
- next
Please see handle-io documentation for more details.
e.g.
const { io, handler } = require('handle-io');
const sleep = io(s => new Promise(resolve => setTimeout(resolve, s * 1000)));
// delayed action example
const myHandler1 = handler(function*(action, { next }) {
yield sleep(1);
return yield next(action);
});
// preserve dispatch order
const myHandler2 = handler(function*(action, { next, dispatch }) {
const nexted = yield next(action);
yield dispatch({ type: 'DUMMY_ACTION' });
return nexted;
});
// print state
const log = io(console.log);
const myHandler3 = handler(function*(action, { next, getState }) {
const nexted = yield next(action);
const state = yield getState();
yield log(state);
return nexted;
})
Note: A redux handler
acts as an async middleware.
testReduxHandler
testReduxHandler
is an extension of handle-io#testHandler
it adds 3 match*() methods:
- .matchNext() - 2 arguments:
- next argument (assert)
- next return (mock)
- .matchDispatch() - 2 arguments:
- dispatch argument (assert)
- dispatch return (mock)
- .matchGetState() - 1 argument:
- getState return (mock)
e.g.
const { handler } = require('handle-io');
const { testReduxHandler } = require('redux-fun');
const createDummyAction = (payload) => { type: 'DUMMY_ACTION', payload }
const myAction = { type: 'MY_ACTION', payload: {} };
const myHandler4 = handler(function*(action, { dispatch, getState, next }) {
const { value } = yield getState();
yield dispatch(createDummyAction(value));
return yield next(myAction);
})
testReduxHandler(myHandler4, myAction)
.matchGetState({ value: 42 })
.matchDispatch(createDummyAction(42))
.matchNext(myAction, 'returned value')
.shouldReturn('returned value')
.run()
createHandleIOMiddleware
usage:
const { createHandleIOMiddleware } = require('redux-fun');
const handleIOMiddleware = createHandleIOMiddleware(myHandler1, myHandler2, myHandler3, myHandler4)
Selectors
Bind selectors
const { bindSelectors } = require('redux-fun');
const selectors = {
getUsers: (state) => state.users,
getUser: (state, { id }) => state.users[id],
}
const boundSelectors = bindSelectors(selectors, store.getState);
const user = boundSelectors.getUser({ id: 1 });
getOwnProp
getOwnProp
is very useful to use with createSelector from reselect
const { createSelector } = require('reselect');
const { getOwnProp } = require('redux-fun');
const getUsers = (state = {}) => state.users || {}
const getUserByName = createSelector(
getUsers,
getOwnProp('fullName'),
(users, fullName) => users[fullName]
)
getUserByName({ users: { user1: true } }, { fullName: 'user1' }); // => true