The name:
I suggest we call these reducer bundles “ducks”, as in the last syllable of “redux”.
Duck was born in the context of how to improve the folder structure in a Redux application. Out there, the first discussion that you will find will be Folder-by-Type vs Folder-by-Feature as we can see in the next example:

(Folder by type on the left side, and by a feature on the right side)
As you can see, folder by type doesn’t scale well in medium-large applications. On the other hand, by feature, seems that makes sense to gather related content together to foment modularity, portability (we could export easier to another project if we don’t have many dependencies with other modules), and scalability. But, we are still coupling our UI library (React) with our state management (Redux).
Ideally, at the design level, we always want to increase cohesion and decrease coupling things together.
Ducks, give us some rules to help us to follow this principle.
Ducks Rules
A Module (action type, action, reducer) should be structured in the following way:
- MUST declare
export default
a function calledreducer()
. - MUST
export
its action creators as functions. - MUST have action types in the form
npm-module-or-app/reducer/ACTION_TYPES
. - 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.
That will help us a lot in terms of scalability in the medium applications, but if our applications, keep growing we will realize that a single file for a feature will become like spaghetti file code as well. At that point, the next solution was born, named Re-Ducks.
Re-Ducks
The main difference between Re-Ducks and Ducks is about instead of using a single Duck file we move into separate folders. In that way your structure folder should look like the following way:

As we see, now we have a root ducks/index.ts
and one dock two docks named catalog
and common
.
So the ducks/index.ts
looks like:

And catalog
dock looks like:

So, as you can see, as a default we will export our reducer
. And then the catalogOperations
ystateSelectors
will be exported in a non default way.
Then we will have access from them in the view:

And the root reducer could be imported in our store.ts
as we can see in the following image:

I hope, you are following me about the benefit and power about this great structure proposal!