HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
erikras
ducks-modular-redux
JavaScript2016–2025
erikras / ducks-modular-redux

ducks-modular-redux

A proposal for bundling reducers, action types and actions when using Redux

16Distinct people
22Mentions
0Explicit recommenders
9.5KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

A proposal for bundling reducers, action types and actions when using Redux

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 4:00:59 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year22 dated mentions

Observed mentions: 2016-06-12 22:57:15 UTC to 2025-11-07 21:50:08 UTC.

02468102016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 5 mentions; 1 submissions, 4 comments20162017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 9 mentions; 2 submissions, 7 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments20202021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC514
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC927
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC211
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC303
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC101
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC000
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC000
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC000
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC101
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC101

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
Ducks: Redux Reducer Bundles I find as I am building my redux app, one piece of functionality at a time, I keep needing to add {actionTypes, actions, reducer} tuples for each use case. I have been keeping these in separate files and even separate folders, however 95% of the time, it's only one reducer/actions pair that ever needs their associated actions. To me, it makes more sense for these pieces to be bundled together in an isolated module that is self contained, and can even be packaged easily into a library. The Proposal Example See also: Common JS Example. // widgets.js // Actions const LOAD = 'my-app/widgets/LOAD'; const CREATE = 'my-app/widgets/CREATE'; const UPDATE = 'my-app/widgets/UPDATE'; const REMOVE = 'my-app/widgets/REMOVE'; // Reducer export default function reducer(state = {}, action = {}) { switch (action.type) { // do reducer stuff default: return state; } } // Action Creators export function loadWidgets() { return { type: LOAD }; } export function createWidget(widget) { return { type: CREATE, widget }; } export function updateWidget(widget) { return { type: UPDATE, widget }; } export function removeWidget(widget) { return { type: REMOVE, widget }; } // side effects, only as applicable // e.g. thunks, epics, etc export function getWidget () { return dispatch => get('/widget').then(widget => dispatch(updateWidget(widget))) } Rules A module... MUST export default a function called reducer() MUST export its action creators as functions MUST have action types in the form npm-module-or-app/reducer/ACTION_TYPE MAY export its action types as UPPER_SNAKE_CASE, if an external reducer needs to listen for them, or if it is a published reusable library These same guidelines are recommended for {actionType, action, reducer} bundles that are shared as reusable Redux libraries. Name Java has jars and beans. Ruby has gems. I suggest we call these reducer bundles "ducks", as in the last syllable of "redux". Usage You can still do: import { combineReducers } from 'redux'; import * as reducers from './ducks/index'; const rootReducer = combineReducers(reducers); export default rootReducer; You can still do: import * as widgetActions from './ducks/widgets'; ...and it will only import the action creators, ready to be passed to bindActionCreators(). Actually, it'll also import default, which will be the reducer function. It'll add an action creator named default that won't work. If that's a problem for you, you should enumerate each action creator when importing. There will be some times when you want to export something other than an action creator. That's okay, too. The rules don't say that you can only export action creators. When that happens, you'll just have to enumerate the action creators that you want. Not a big deal. import {loadWidgets, createWidget, updateWidget, removeWidget} from './ducks/widgets'; // ... bindActionCreators({loadWidgets, createWidget, updateWidget, removeWidget}, dispatch); Example React Redux Universal Hot Example uses ducks. See /src/redux/modules. Todomvc using ducks. BattleCry generators There are configurable BattleCry generators ready to be downloaded and help scaffolding ducks: npm install -g battlecry cry download generator erikras/ducks-modular-redux cry init duck Run cry --help to check more info about the generators available; Implementation The migration to this code structure was painless, and I foresee it reducing much future development misery. Although it's completely feasable to implement it without any extra library, there are some tools that might help you: extensible-duck - Implementation of the Ducks proposal. With this library you can create reusable and extensible ducks. saga-duck - Implementation of the Ducks proposal in Typescript with sagas in mind. Results in reusable and extensible ducks. redux-duck - Helper function to create Redux modules using the ducks-modular-redux proposal modular-redux-thunk - A ducks-inspired package to help organize actions, reducers, and selectors together - with built-in redux-thunk support for async actions. molecular-js - Set of utilities to ease the development of modular state management patterns with Redux (also known as ducks). ducks-reducer - Function to combine ducks object reducers into one reducer (equivalent to combineReducers), and function ducks-middleware to combine ducks object middleware into one single middleware compatible with applyMiddleware. simple-duck - Class based implementation of modules system, inspired by ducks-modular-redux. All OOP benefits like inheritance and composition. Support combining of duck-module classes and regular reducer functions using combineModules function. Please submit any feedback via an issue or a tweet to @erikras. It will be much appreciated. Happy coding! -- Erik Rasmussen Translation 한국어 中文 Türkçe Photo credit to Airwolfhound.
Read the full README on GitHub

What Hacker News says

5 sources
For a simple app your code works fine. You will have trouble when it scales. We have migrated a load of model logic from Angular to redux and redux saga, once you get your head around a nice structure then its a dream. I created a gist for you to check out [1]. Maybe also check out the concept of Redux Ducks [2]. I now find our code easy to read, share and test - unlike our massive Angular app. Also as somebody else comments, you should make sure the only way you talk to your store is through a reducer dispatcher. Regarding component states, find some reading on components v containers [3] - we even have 2 separate folders for the different types. Once mastered and implemented, most components are small and again easy to test. [1] https://gist.github.com/anonymous/a20f603f9922742bd3cea7a08c... [2] https://github.com/erikras/ducks-modula
Read the rest
In Show HN: Build your first real world React.js application
Personally I found that using redux for everything ends up spreading a ton of boilerplate everywhere. Action creators, reducer, the dumb component itself, the HOC. All that adds up and is a lot of work for a simple component. We ended up going with a hybrid setup. Our components are all dumb, and our "pages" are the only connected components. We also started using ducks[1] instead of spreading the reducer/actions everywhere whenever it makes sense. [1] https://github.com/erikras/ducks-modular-redux
In MobX – Simple, scalable state management for React
Having worked with Redux on a few different projects I'd probably recommend a different approach than the one outlined in this tutorial. One of the great things about React is the advice that you can put more in a single file than you used to be able to. We seem to have forgotten that concept when it comes to the data layer of most Redux applications I see. I would suggest that people check out the Ducks pattern: https://github.com/erikras/ducks-modular-redux To sum it up: your constants, action creators, action handlers, and reducer all go in a single file. You can export anything you need from a duck file, and the default export for any duck must be the reducer. This ends up being really nice - no more rapidly switching back and forth between action creator files, reducer files, your constant files, etc. It also allows you to easily col
Read the rest
lect all your ducks and attach them to a redux store (thanks to the default export.) Some suggest putting any data fetching in the ducks as well - I think this can be handled on a case-by-case basis - I tend to prefer to keep my data managers in a separate "services" folder though, which are just files that export async functions like "fetchUser(id)" or "fetchArticles()" Ultimately there are many different valid ways to structure your code, this is just one way that I've found to be much more enjoyable.
In A SoundCloud client in React and Redux

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.