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

mindfront-redux-utils-immutable

v2.1.2

Published

utilities for working with redux and immutable.js

Downloads

1,202

Readme

mindfront-redux-utils-immutable

Build Status Coverage Status semantic-release Commitizen friendly npm version

Legacy build note

If you are building for legacy browsers with webpack or a similar bundler, make sure to add a rule to transpile this package to ES5.

combineReducers

import { combineReducers } from 'mindfront-redux-utils-immutable'
function combineReducers(
  reducers: {[key: any]: Reducer},
  createInitialState?: (initialValues: Object) => Immutable.Collection.Keyed | Record = Immutable.Map
): Reducer

Like combineReducers from redux, except that the combined reducer operates on immutable keyed collections or records.

Unlike the combineReducers implementation from the redux-immutable package, this implementation is highly optimized. If multiple reducers have actionHandlers, they will be recombined so that all mutations for one of those actions are done inside a single state.withMutations call.

As an example, let's say we have the following reducer:

const setUser = (oldUser, action) => action.newUser
const updateUser = (user, action) => user.merge(action.payload)
const incUserChangeCount = (count = 0) => count + 1

const reducer = combineReducers({
  user: createReducer({
    [SET_USER]: setUser,
    [UPDATE_USER]: updateUser,
  }),
  userChangeCount: createReducer({
    [SET_USER]: incUserChangeCount,
  }),
})

combineReducers essentially works like the following:

const reducer = createReducer({
  [SET_USER]: (state, action) =>
    state.withMutations((state) => {
      state.update('user', (oldUser) => setUser(oldUser, action))
      state.update('userChangeCount', (count) =>
        incUserChangeCount(count, action)
      )
    }),
  [UPDATE_USER]: (state, action) =>
    state.update('user', (user) => updateUser(user, action)),
})

Caveats

Due to this optimization, unlike other combineReducers implementations, if you call the combined reducer with an empty collection, it will not set the initial values for any reducers skipped by optimization. For example:

import { Map } from 'immutable'
import { createReducer } from 'mindfront-redux-utils'
import { combineReducers } from 'mindfront-redux-utils-immutable'

const reducer = combineReducers({
  a: createReducer(0, {
    a: (state) => state + 1,
    ab: (state) => state + 1,
  }),
  b: createReducer(0, {
    ab: (state) => state + 1,
    b: (state) => state + 1,
  }),
})

reducer(undefined, { type: 'a' }) // Map({a: 1, b: 0})
reducer(Map(), { type: 'a' }) // Map({a: 1})
reducer(Map(), { type: 'b' }) // Map({b: 1})
reducer(Map(), { type: 'ab' }) // Map({a: 1, b: 1})

As long as you handle missing keys everywhere in your code, this is not a problem.

Another workaround is to use Records with the desired initial values in the Record constructor:

import { Record } from 'immutable'
import { createReducer } from 'mindfront-redux-utils'
import { combineReducers } from 'mindfront-redux-utils-immutable'

const MyRecord = Record({ a: 0, b: 0 })

const reducer = combineReducers(
  {
    a: createReducer(0, {
      a: (state) => state + 1,
      ab: (state) => state + 1,
    }),
    b: createReducer(0, {
      ab: (state) => state + 1,
      b: (state) => state + 1,
    }),
  },
  MyRecord
)

reducer(undefined, { type: 'a' }) // MyRecord({a: 1, b: 0})
reducer(MyRecord(), { type: 'a' }) // MyRecord({a: 1, b: 0})
reducer(MyRecord(), { type: 'b' }) // MyRecord({b: 1, b: 0})
reducer(MyRecord(), { type: 'ab' }) // MyRecord({a: 1, b: 1})

subpathReducer

import { subpathReducer } from 'mindfront-redux-utils-immutable'
function subpathReducer(
  path: Array<any> | (action: Action) => Array<any>,
  initialState?: Immutable.Collection.Keyed | Record
): Reducer => Reducer

Creates a reducer that applies the decorated reducer at the given path within the state. This is basically equivalent to (state = initialState, action) => state.updateIn(path, reducer) except that if the decorated reducer has actionHandlers, the created reducer will have corresponding actionHandlers so that other utils can optimize it.

If you pass a function for path, subpathReducer will get the actual path by calling path(action) for each action.