npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

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

Readme

reducer-pipe npm package Travis Coveralls

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 to initialState.
  • 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 as currentState). It must compare with previousState (defaults to initialState) 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 chain redux 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.