Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

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: about 2 months ago
JSON representation

:wrench: - Redux functional programming utilities

Awesome Lists containing this project

README

        

# redux-fun :wrench:

[![CircleCI branch](https://img.shields.io/circleci/project/github/guillaumearm/redux-fun/master.svg)](https://circleci.com/gh/guillaumearm/redux-fun)
[![codecov](https://codecov.io/gh/guillaumearm/redux-fun/branch/master/graph/badge.svg)](https://codecov.io/gh/guillaumearm/redux-fun)
[![npm](https://img.shields.io/npm/v/redux-fun.svg)](https://www.npmjs.com/package/redux-fun)
[![Greenkeeper badge](https://badges.greenkeeper.io/guillaumearm/redux-fun.svg)](https://greenkeeper.io/)
[![NSP Status](https://nodesecurity.io/orgs/trapcodien/projects/b0aa847e-a5c4-4758-9aab-d4e23d15d3d1/badge)](https://nodesecurity.io/orgs/trapcodien/projects/b0aa847e-a5c4-4758-9aab-d4e23d15d3d1)
[![dependencies Status](https://david-dm.org/guillaumearm/redux-fun/status.svg)](https://david-dm.org/guillaumearm/redux-fun)
[![devDependencies Status](https://david-dm.org/guillaumearm/redux-fun/dev-status.svg)](https://david-dm.org/guillaumearm/redux-fun?type=dev)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/guillaumearm/redux-fun/blob/master/CONTRIBUTING.md)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Join the chat at https://gitter.im/redux-fun/Lobby](https://badges.gitter.im/redux-fun/Lobby.svg)](https://gitter.im/redux-fun/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](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
```
----------------------