redux-xforms

1.5.0 • Public • Published

redux-xforms

Build Status npm version

redux-xforms is a collection of reducer transformers (higher-order reducers). They can be used to define reducers by direct composition of simpler transformers.

Reducer transformers are similar to transducers, but lacks the completion step. It's a special case of higher-order reducers, functions that transform a reducer to another reducer:

xform: reducer -> reducer
reducer: state, input -> state

See full documentation

Story

As wrote this article on the topic "Reducer composition with Higher-Order Reducers", it struck me that these Higher-Order Reducers could be decomposed into much simpler transformations. So, I started putting together a colletion, and here it is redux-xforms!

Installation

npm install --save redux-xforms

Example usage

Setting up a byFilterName transformer:

import { createByKey, createGetByKey } from 'redux-xforms'
 
const hasFilterName = action => action.hasOwnProperty('filterName')
const mapActionToFilterName = action => action.filterName
 
// we can call this later with a reducer to get the transform
const createByFilter = createByKey(hasFilterName, mapActionToFilterName)
 
const createGetByFilter = createGetByKey(mapActionToFilterName)

When createByFilter is called with a reducer, the transformers will be applied one by one, from right to left. When calling the transformed reducer with an action, it will come in from the left.

const ACTION_TYPE = 'ACTION_TYPE'
const reducer = (state = { nested: null }, action) => {
  if (action.type === ACTION_TYPE) {
    return { nested: action.payload }
  }
  return state
}
 
const transformedReducer = createByFilter(reducer)
const getNestedState = createGetByFilter(state => state.nested)
 
// reducing actions:
const state = [ {}, {
  type: ACTION_TYPE,
  payload: 'some-payload',
  filterName: 'myFilterName',
} ].reduce(transformedReducer, undefined)
 
console.log(state)
// { myFilterName: { nested: 'some-payload' } }
 
console.log(getNestedState(state, { filterName: 'myFilterName' }))
// 'some-payload'

createByKey is simply a composition of other reducer transformers.

import { withInitialState, withFilter, updateSlice, isolateSlice } from 'redux-xforms'
import { compose } from 'redux'
 
const createByFilter = (predicate, mapActionToKey) => compose(
  withInitialState({}), // inject initial state as {}
  withFilter(predicate), // let through if action has filterName
  updateSlice(mapActionToKey), // update a single key in the state
  isolateSlice(mapActionToKey) // run the reducer on a single state slice
)
 
// we can transform (state, input -> state) selectors as well
const createGetByFilter = mapActionToFilterName => isolateSlice(mapActionToFilterName)

Package Sidebar

Install

npm i redux-xforms

Weekly Downloads

17

Version

1.5.0

License

MIT

Unpacked Size

376 kB

Total Files

29

Last publish

Collaborators

  • mhelmer