redux-immutable

Adapts Redux's combineReducers to work seamlessly with Immutable.js state trees.

Library
npm
v4.0.0
1,866stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity0
Maintenance20
Community52
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
58/100Fair
Architecture70
Code Quality78
Innovation55
Learning Curve30

redux-immutable provides a drop-in equivalent of Redux’s own combineReducers that understands Immutable.js collections instead of plain JavaScript objects. Redux’s built-in implementation assumes the state tree is a plain object, which breaks the moment a store’s initial state is an Immutable.Map, Immutable.Record, or similar collection — this package fixes that mismatch so teams can keep using Immutable.js for their store state without hand-rolling their own root reducer.

The API mirrors Redux’s combineReducers almost exactly, taking a map of slice reducers and an optional getDefaultState factory (defaulting to Immutable.Map), so migrating an existing Redux app to Immutable.js state — or vice versa — requires touching only the store setup code, not every individual reducer.

What You Get

  • A combineReducers function with the same call signature as Redux’s own, so existing reducer maps can be swapped in without restructuring application code
  • Support for any Immutable.js collection as root state — Map, OrderedMap, or a custom Record — via a configurable getDefaultState argument
  • Development-mode invariant warnings (mirroring Redux core’s own checks) that flag unexpected state shapes or unknown reducer keys via console.error
  • An explicit runtime error when a child reducer returns undefined, matching Redux’s own contract for reducers that must always return a defined state

Common Use Cases

  • Powering the root reducer of a Redux store whose state is normalized into Immutable.js collections for structural-sharing performance
  • Nesting combineReducers calls to build a multi-level Immutable state tree, e.g. combining feature-level reducers under a top-level outer/inner hierarchy
  • Migrating a legacy Redux + Immutable.js codebase (common in React apps built during Redux’s early conventions era) while keeping the reducer composition pattern intact
  • Supplying a custom Immutable.Record as the default state shape so the store enforces a fixed set of top-level keys with typed defaults

Under The Hood

Architecture The library is a flat, functional translation layer with no classes or DI: combineReducers (src/combineReducers.ts) closes over a reducers map and returns a new reducer function that, on each dispatch, iterates the reducer keys inside an Immutable.Collection.withMutations block — reading each slice’s current value, invoking its reducer, validating the result via validateNextState, and writing it back — so the whole tree is updated as one batched, structurally-shared operation instead of a plain-object spread. Supporting concerns are split into small single-function utility modules (getStateName, getUnexpectedInvocationParameterMessage, validateNextState) that mirror the same invariant checks Redux’s own combineReducers performs, re-implemented against Immutable’s isCollection/toSeq API instead of Object.keys. Because the public surface is a single function with one optional parameter, there is effectively nothing to break by changing internals — the only real dependency a consumer takes on is the call signature.

Tech Stack Written in TypeScript (strict mode, targeting ES5/CommonJS via tsc), with immutable ^4.0.0 declared as a peer dependency so the host application controls the exact Immutable.js version. Tests run via Mocha + Chai through ts-node/register, linting is enforced with eslint-config-canonical and a Husky pre-commit hook, and releases are cut with semantic-release. Travis CI (.travis.yml) runs the test suite on push. No bundler or framework is involved — the package is small enough to ship as plain compiled CommonJS.

Code Quality A dedicated test suite (tests/combineReducers.ts, tests/utilities/*.ts) exercises pass-through state, new-state creation, nested combineReducers composition, and every supported default-state shape (custom Record, OrderedMap, and a custom factory function), each asserting both the returned value and its runtime type via instanceof. Error handling is explicit rather than swallowed: an invalid reducer result throws a descriptive Error naming the offending reducer and action type, and shape mismatches surface as console.error warnings in non-production builds — the same invariant-violation UX Redux itself uses. Naming and formatting are enforced through ESLint’s canonical config, and TypeScript strict mode catches type misuse at compile time, though several of the reducer/action parameters are still typed as any, and no .d.ts-level documentation comments accompany the exported function.

API Design The entire public API is one function with a call signature deliberately identical to Redux’s own combineReducers, which makes adoption close to zero-boilerplate for anyone already familiar with Redux — the only new concept to learn is the optional getDefaultState argument for supplying a non-Map root state. Documentation lives entirely in the README’s inline usage examples rather than dedicated example files or a docs site, and the package has been functionally stable and unmaintained since 2022, so its DX is frozen at whatever Redux and Immutable.js conventions looked like in that era.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search