https://github.com/guillaumearm/redux-fun
:wrench: - Redux functional programming utilities
https://github.com/guillaumearm/redux-fun
fp functional-programming handler middleware reducer redux selector updater
Last synced: 5 months ago
JSON representation
:wrench: - Redux functional programming utilities
- Host: GitHub
- URL: https://github.com/guillaumearm/redux-fun
- Owner: guillaumearm
- License: mit
- Created: 2017-12-30T14:17:41.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2020-06-02T18:15:22.000Z (over 5 years ago)
- Last Synced: 2025-05-06T05:05:55.955Z (6 months ago)
- Topics: fp, functional-programming, handler, middleware, reducer, redux, selector, updater
- Language: JavaScript
- Homepage:
- Size: 5.13 MB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 24
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# redux-fun :wrench:
[](https://circleci.com/gh/guillaumearm/redux-fun)
[](https://codecov.io/gh/guillaumearm/redux-fun)
[](https://www.npmjs.com/package/redux-fun)
[](https://greenkeeper.io/)
[](https://nodesecurity.io/orgs/trapcodien/projects/b0aa847e-a5c4-4758-9aab-d4e23d15d3d1)
[](https://david-dm.org/guillaumearm/redux-fun)
[](https://david-dm.org/guillaumearm/redux-fun?type=dev)
[](https://github.com/guillaumearm/redux-fun/blob/master/CONTRIBUTING.md)
[](http://commitizen.github.io/cz-cli/)
[](https://gitter.im/redux-fun/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](https://github.com/semantic-release/semantic-release)
Redux functional programming utilities
## Install
```bash
$ npm install --save redux-fun
```
## Documentation
### Reducers
##### Compose reducers
```js
const { composeReducers, pipeReducers } = require('redux-fun');
const reducer_1 = composeReducers(r3, r2, r1);
const reducer_2 = pipeReducers(r1, r2, r3);
```
##### Convert updaters
```js
const { toReducer } = require('redux-fun');
const updater = (action) => state => state;
const reducer = toReducer(updater);
```
----------------------
### Updaters
##### updater with initial state
```js
const { withDefaultState } = require('redux-fun');
// normal
const updater_1 = withDefaultState({}, action => state => state);
// curried
const updater_2 = withDefaultState({})(action => state => state);
```
----------------------
### Middlewares
##### Compose middlewares
```js
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
```js
const { preserveAsyncSeries } = require('redux-fun');
const middleware_1 = preserveAsyncSeries('ACTION_TYPE')
const middleware_2 = preserveAsyncSeries(['ACTION_TYPE_1', 'ACTION_TYPE_2'])
```
----------------------
### Handlers
A [Handler](https://github.com/guillaumearm/handle-io/#handlers) from the [handle-io](https://github.com/guillaumearm/handle-io) library can be tranformed into redux middleware using [createHandleIOMiddleware](https://github.com/guillaumearm/redux-fun#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](https://github.com/guillaumearm/handle-io/#io) functions :
- **getState**
- **dispatch**
- **next**
Please see [handle-io documentation](https://github.com/guillaumearm/handle-io/#readme) for more details.
**e.g.**
```js
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](https://github.com/guillaumearm/handle-io/#test-side-effects-orchestration-without-pain)
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.**
```js
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:**
```js
const { createHandleIOMiddleware } = require('redux-fun');
const handleIOMiddleware = createHandleIOMiddleware(myHandler1, myHandler2, myHandler3, myHandler4)
```
----------------------
### Selectors
##### Bind selectors
```js
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](https://github.com/reactjs/reselect)
```js
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
```
----------------------