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 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 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

22 sources
What "naming conventions and file structures" are you referring to? I don't think Dan ever really popularized anything like that for _React_. If you're thinking of _Redux_, are you referring to the early conventions of "folder-by-type" file structures? ie `actions/todos.js`, `reducers/todos.js`, `constants/todos.js`? If so, there's perfectly understandable reasons why we ended up there: - as programmers we try to "keep code of different kinds in different files", so you'd separate action creator definitions from reducer logic - but we want to have consistency and avoid accidental typos, especially in untyped plain JS, so you'd extract the string constants like `const ADD_TODO = "ADD_TODO"` into their own file for reuse in both places To be clear that was never a requirement for using Redux, although the docs did show that pattern. We
Read the rest
eventually concluded that the "folder-by-feature" approach was better: - https://redux.js.org/style-guide/#structure-files-as-feature... and in fact the original "Redux Ducks" approach for single-file logic was created by the community just a couple months after Redux was created: - https://github.com/erikras/ducks-modular-redux which is what we later turned into "Redux slices", a single file with a `createSlice` call that has your reducer logic and generates the action creators for you: - https://redux.js.org/tutorials/essentials/part-2-app-structu...
In Dead Framework Theory
Hi, I'm a Redux maintainer. A few notes here: - It was never necessary to write `mapDispatchToProps` as a function. `connect` always supported an "object shorthand", where you passed in an object full of action creators, and we recommended that as the default: https://react-redux.js.org/using-react-redux/connect-mapdisp... . That said, yes, with hooks we just give you `const dispatch = useDispatch()` and let you use that as necessary. - The split across multiple files was never _necessary_. Splitting code like `actions/todos.js`, `reducers/todos.js` , and `constants/todos.js` was _common_ (and admittedly shown in the docs), but Redux itself never cared about how you organized your code at the runtime level. The single-file "ducks pattern" ( https://github.com/erikras/ducks-modular-redux ) was proposed very early on and was always some
Read the rest
thing users could do. - Labeling "global reducer, serializable state, serializable actions" as "not bringing anything worthwhile" seems like a complete misunderstanding of Redux's design and purpose. Redux was created to give you a consistent data flow architecture, and the ability to make it easier to understand when, why, and how your state gets updated. Centralizing state and having consolidated reducer logic means you _always_ know "go look at the reducers" to see what state the app has, what actions _can_ occur in the app, and how the state gets updated for each action that can occur. Serializable state and actions enable the Redux DevTools, which show you the history of dispatched actions, the action and state contents for each dispatch, and the final resulting state after each dispatch. So, the design constraints are fully intentional to give you the benefits that make the app's behavior easier to understand. Finally, note that Redux usage patterns changed dramatically in 2019, with the release of our official Redux Toolkit package and the React-Redux hooks API. RTK includes methods that simplify all the common Redux use cases: setting up a Redux store with good defaults, writing reducers with simpler immutable update logic (and getting all the action creators generated for free), patterns like async requests / reactive side effects / normalizing items by ID, and even our RTK Query data fetching layer for fully declarative data fetching and caching. Redux is not the right choice for all apps, and there's a lot of other good alternative tools in the ecosystem. But Redux's design _is_ very intentional, those constraints were put in place to enable the desired benefits, and Redux usage today is much easier thanks to RTK.
In React Labs: What We've Been Working On – February 2024
Hi, I'm a Redux maintainer. There's a much better solution than what this blog describes. We've just released a new package called Redux Starter Kit [0], which is meant to provide opinionated defaults and simplify writing common Redux code patterns. It's already written in TypeScript, and works great in TS apps. In particular, the `createSlice` function [1] allows you to provide reducer functions that use "mutative" update logic (thanks to using the Immer library [2] internally), and auto-generates action types and action creators based on the provided reducers. Really, there's no reason to write an action creator or action type by hand ever again. `createSlice` also makes it really easy to organize your Redux logic using the single-file-per-feature "ducks" pattern [3] The "Advanced Tutorial" page [4] shows how to use RSK with TypeScr
Read the rest
In Reducing Redux Boilerplate in TypeScript
Whenever a Redux thread pops up, there's inevitably complaints about "boilerplate". I'd like to pre-empt those complaints a bit by pointing out that, per part 2 of my post, it's entirely up to you how much abstraction you use in your own Redux app. If you want use Redux for a particular use case, someone has probably already written an addon or utility to help solve that problem, and I've got them listed in my Redux addons catalog [0]. If you don't want to edit multiple files, use the "ducks" pattern to put actions and reducers in a single file [1]. If you don't like writing action constants by hand, use one of the dozens of action/reducer generation utilities out there [2] [3]. If you don't want to manage normalized data by hand, there's many addon libraries to help with that [4]. I specifically show off one of them, Redux-ORM [5],
Read the rest
in my "Practical Redux" tutorial series [6]. I love all the tools and addons that people are building on top of Redux. One of my favorite quotes is from a Redux issue thread: > Redux is a generic framework that provides a balance of just enough structure and just enough flexibility. As such, it provides a platform for developers to build customized state management for their use-cases, while being able to reuse things like the graphical debugger or middleware. A few months ago I opened up a Redux issue thread to discuss further ways that we could help make it easier for people to use Redux, and solve complaints about "boilerplate". The discussion kind of trailed off, but I would love to have more discussion and ideas for building useful new tools on top of and around Redux to help people solve problems and build useful applications. Please join the discussion here: https://github.com/reactjs/redux/issues/2295 [0] https://github.com/markerikson/redux-ecosystem-links [1] https://github.com/erikras/ducks-modular-redux [2] https://github.com/markerikson/redux-ecosystem-links/blob/ma... [3] https://github.com/markerikson/redux-ecosystem-links/blob/ma... [4] https://github.com/markerikson/redux-ecosystem-links/blob/ma... [5] https://github.com/tommikaikkonen/redux-orm [6] http://blog.isquaredsoftware.com/series/practical-redux
In Idiomatic Redux: Implementation and Intent
A few possible options: - Put all the action types, action types, and reducers for a given portion of the application into one file. This is known as the "ducks" structure, per https://github.com/erikras/ducks-modular-redux . - Use a utility library like https://github.com/acdlite/redux-actions to generate action types and action creators for you - Write middleware to manage common logic for your application such as API calls - Skip writing action creators and declaring action constants, and just have components do `this.props.dispatch({type : "SOME_ACTION"})`. I don't recommend the last approach, but it's _totally_ up to you, especially because what you regard as "too much boilerplate" is going to be a personal opinion. One person's "too much boilerplate" is another person's "explicit and easy to trace through the system".
In Build Yourself a Redux
You don't actually have to do this if it bothers you. You can just use the strings inline, but the author (and many of those using Redux) finds it helps to reduce errors, by instantly pointing out typos. There are also patterns to reduce the import issue. For example, https://github.com/erikras/ducks-modular-redux. I prefer defining my actions with my action creators in one big index, but the point is that there is absolutely a way to mitigate this concern if it bothers you :)
In Build Yourself a Redux

Showing the 15 most recent of 22 sources. Enable JavaScript to search and browse every indexed mention.

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.