Modular Redux Thunk

A ducks-inspired package to help organize actions, reducers, and selectors together.
Alternatives To Modular Redux Thunk
Project NameStarsDownloadsRepos Using ThisPackages Using ThisMost Recent CommitTotal ReleasesLatest ReleaseOpen IssuesLicenseLanguage
Redux Orm2,96582378 months ago70August 11, 2021115mitJavaScript
NOT MAINTAINED – A small, simple and immutable ORM to manage relational data in your Redux store.
Reatom8691618 hours ago68June 13, 202238mitTypeScript
Reatom - the ultimate state manager
Re Ducks770
6 years ago1JavaScript
An attempt to extend the original proposal for redux modular architecture:
Autodux589166 months ago16July 28, 201932mitJavaScript
Automate the Redux boilerplate.
Reactjs Shopping Cart205
7 months ago7JavaScript
example of shopping cart implemented in react.js and redux.js
React Test Demo156
4 years agoJavaScript
Web 前端单元测试到底要怎么写?看这一篇就够了
Extensible Duck143543 years ago12September 13, 20196mitJavaScript
Modular and Extensible Redux Reducer Bundles (ducks-modular-redux)
Redux Rest Easy105123 years ago35July 15, 20196mitJavaScript
⛳ Redux/React/React Native framework handling network requests, state management, selectors, caching and much more
Reduxsimple10062 years ago19December 20, 202115mitC#
Simple Stupid Redux Store using Reactive Extensions
Redux Api Call6852a year ago66August 16, 2022mitJavaScript
One declarative API to create reducers, action creators and selectors for any API calls
Alternatives To Modular Redux Thunk
Select To Compare

Alternative Project Comparisons

Modular Redux Thunk

Dependency Status npm version Build Status

A ducks-inspired package to help organize actions, reducers, and selectors together - with built-in redux-thunk support for async actions.


  • Each module is only aware of it's own state. Reducer's don't care or know about each other's state.
  • Only a module should be aware of how its state is structured. You define all actions, reducers, and selectors in each module that manipulate and retrieve data from that reducer.
  • You can define global actions and global selectors. Occasionally, you'll need to dispatch actions or define selectors that use multiple reducers. Global actions have access to all defined actions, and global reducers have access to all defined selectors.
  • Connected components should not assume to know how the store is structured. When creating connected components, you should never reference the state directly. Instead, use the selectors you've defined in each module, and any global reducers, to return that data.
  • You should not have to update your connected components when changing your store's structure. This is a huge bonus. Since all components use pickActions and selectors (more about that below), you can change your store's structure as much as you'd like. For example, you can move a data node from one module to another without affecting your components - as along as you maintain your actions and update your selectors to reflect the latest structure.


npm install --save modular-redux-thunk

import createStore from 'modular-redux-thunk';

const { store, pickActions, selectors } = createStore(myModules);

You can also include custom reducers, middleware, or enhancers. For example, if you install react-router and redux-freeze:

npm install --save react-router
import createStore from 'modular-redux-thunk';
import { routerReducer } from 'react-router-redux';

const { store, pickActions, selectors } = createStore(myModules, {
	reducers: {
		routing: routerReducer
	enhancers: []


Let's say your app will be storing the following information in the state:

  • A list of chips you sell
  • The logged-in-user's favorite chips
  • A list of drinks you sell
  • The logged-in-user's favorite drink


const actions = {};
const reducers = {};
const selectors = {};
const ACTION_PREPEND = 'my-react-app/chips';

reducers.favorite = (state = 'unknown', action) => {
  switch(action.type) {
    case SET_FAVORITE_CHIPS: return action.newFav;
    default: return state;
actions.setFavoriteChips = (newFav) => {
  return {
selectors.getFavoriteChips = (chipsState) => chipsState.favorite;

reducers.chipsForSale = (state = [], action) => {
  switch(action.type) {
    case SET_CHIPS_FOR_SALE: return action.chips;
    default: return state;
actions.setChipsForSale = (chips) => {
  return {
selectors.getChipsForSale = (chipsState) => chipsState.chips;

export default { actions, reducers, selectors };


import { combineModules, settableValue } from 'modular-redux-thunk';
const actions = {};
const reducers = {};
const selectors = {};
const ACTION_PREPEND = 'my-react-app/drinks';

// You can also define individual modules and combine them
const favorite = {
	reducer: (state = 'unknown', action) => {
	  switch(action.type) {
	    case SET_FAVORITE_DRINK: return action.newFav;
	    default: return state;
	actions: {
		setFavoriteDrink: (newFav) => ({
	selectors: {
		getFavoriteDrink: (favoriteDrinkState) => favoriteDrinkState;

// Or even use a module creator function to automate this common pattern
const drinksForSale = settableValue([], 'getDrinksForSale', 'setDrinksForSale');

export default combineModules({


export const getUserFavorites = (selectors, state) => {
  return {
    chips: selectors.getFavoriteChips(state),
    drink: selectors.getFavoriteDrink(state)


export const setUserFavorites = (actions, favChips, favDrink) => {
  return function(dispatch) {


import createStore from 'modular-redux-thunk';

import chips from './chips.js';
import drinks from './drinks.js';
import * as globalActions from './actions.js';
import * as globalSelectors from './selectors.js';

const modules = {chips, drinks};

const globals = {
  globalActions: globalActions,
  globalSelectors: globalSelectors

const { store, selectors, pickActions } = createStore(modules, globals);
export { store, selectors, pickActions };


import React from 'react';
import { Provider, connect } from 'react-redux';
import { store, selectors, pickActions } from './reducers';

// Create the connected component
class _AppComponent extends React.Component {
  render() {
    const { favorites } = this.props;

    const statement = `My favorite kind of chips are ${favorites.chips} and drink is ${favorites.drink}!`;
    return (<div>{ statement }</div>);
_AppComponent.propTypes = {
  setFavoriteChips: React.PropTypes.func,
  favorites: React.PropTypes.object
const AppComponent = connect(state => {
  return {
    favorites: selectors.getUserFavorites(state)
}, pickActions('setFavoriteChips'))(_ChipsComponent);

const AppWrapper = (props) => {
	return (<Provider store={ store }><AppComponent /></Provider>);

  <AppWrapper />,

API Reference


A module object consists of:

  • One of the following:
    • reducer - A standard Redux reducer function. Each reducer should be defined in it's simplest form. For example, define reducers that are strings, booleans, numbers, or arrays.
    • reducers - An object of Redux reducer functions. If you choose this option, its value will be run through Redux.combineReducers.
  • actions (object): A map of action creator functions. Each action should return an object with, at the very least, a type property.
  • selectors (object): Selector functions that connected components call to get parts of the state. A selector's first and only argument is the module's current state.

createStore(modules, [preloadedState], [globalDefinitions], [reduxConfig])

Creates a Redux store that combines your reducers into a single and complete state tree.


  1. modules (object): Defines the global structure of the store. Each key represents the modules's location in the store, and the value is the module object itself. Module objects are described above.
  2. [preloadedState] (object): Initial state passed to Redux.
  3. [globalDefinitions] (object): Pass in any global actions or selectors. Globals are given access to all reducers. You can pass in the following keys:
    • [globalActions] (object): Actions that can themselves perform actions from any reducer. Global actions differ from reducer actions in that the first argument will always be:
      • combinedActions (object): All combined actions from reducers. This allows you to reference reducer-defined actions.
    • [globalSelectors] (object): Selectors that have access to all reducer-defined selectors. Global selectors differ from reducer selectors in that the first argument will always be:
      • combinedSelectors (object): All combined selectors from reducers. This allows you to reference reducer-defined selectors.
  4. [reduxConfig] (object): Any custom redux config. You can pass in the following keys:
    • [reducers] (object): Additional reducers you'd like to be added to the store. For example, if using react-router, you can pass in routing which will be added to the store.
    • [middleware] (array): Any custom middleware to be added to the store. redux-thunk is automatically included as a middleware for your convenience.
    • [enhancers] (array): Any custom enhancers to be added to the store, such as redux-freeze. When not in production, redux-devtools-extension is automatically added for your convenience.


Returns an object with the following properties:

  1. store (Store): A Redux store that lets you read the state, dispatch actions
  • and subscribe to changes.
  1. pickActions (function): A function that returns an object of desired actions out of all available actions. Use this instead of passing the actions object to your connected components.
  2. selectors (object): All combined selectors for use when connecting your components.
  3. actions (object): All available actions. You can cherry-pick actions here as opposed to using pickActions.


Takes a map of Module objects and returns a single Module object.

settableValue(initialValue, selectorName, actionName, [actionType])

Creates a module that controls a single value and responds to a single "set" action, as is quite common in Redux.


  1. initialValue - The initial value of the module
  2. selectorName - The name of the module's single selector - usually something like getMyValue
  3. actionName - The name of the module's single action creator - usually something like setMyValue
  4. actionType - Optional. The action's type constant - usually something like SET_MY_VALUE. If not set, it will default to actionName.


  • Finish pending tests
  • / Fix Istanbul (and status)
  • Minify build
  • JS:next?


Commit all changes
npm run build # runs "npm test && npm run clean:build && npm run build && npm run test:build"
npm version "v1.0.0-beta1" -m "Message"
npm publish
git push origin HEAD:master --tags
# Update Changelog
Popular Selector Projects
Popular Reducer Projects
Popular User Interface Components Categories

Get A Weekly Email With Trending Projects For These Categories
No Spam. Unsubscribe easily at any time.