How to structure Redux components/containers
I prefer keeping smart and dumb components in the same file, but use default export for smart component and export for presentation/dumb components. This way you can reduce file noise in your directory structure. Also group your components by "View" i.e. (Administration => [admin.js, adminFoo.js, adminBar.js], Inventory => [inventory.js, inventoryFoo.js, inventoryBar.js], etc).
I have no strong opinion about the component directories, but I like putting the actions, constants and reducers together:
state/
actions/
index.js
...
constants.js
reducers.js
I alias state
with with webpack so in the container components I can import {someActionCreator} from 'state/actions';
.
This way, all the stateful code in the app resides in a single place.
Note that reducers.js
could be split into multiple files simply by making a reducers/
directory like actions/
and you wouldn't have to change any import statements.
In the official examples we have several top-level directories:
components
for “dumb” React components unaware of Redux;containers
for “smart” React components connected to Redux;actions
for all action creators, where file name corresponds to part of the app;reducers
for all reducers, where file name corresponds to state key;store
for store initialization.
This works well for small and mid-level size apps.
When you want to go more modular and group related functionality together, Ducks or other ways of grouping functionality by domain is a nice alternative way of structuring your Redux modules.
Ultimately choose whatever structure works best for you. There is no way Redux authors can know what’s convenient for you better than you do.
This is more a question about best practices / code style, and there is no clear answer. However, a very neat style was proposed in the React redux boilerplate project. It's very similar to what you currently have.
./react-redux-universal-hot-example
├── bin
├── src
│ ├── components // eg. import { InfoBar } from '../components'
│ │ ├── CounterButton
│ │ ├── GithubButton
│ │ ├── InfoBar
│ │ ├── MiniInfoBar
│ │ ├── SurveyForm
│ │ ├── WidgetForm
│ │ └── __tests__
│ ├── containers // more descriptive, used in official docs/examples...
│ │ ├── About
│ │ ├── App
│ │ ├── Home
│ │ ├── Login
│ │ ├── LoginSuccess
│ │ ├── NotFound
│ │ ├── RequireLogin
│ │ ├── Survey
│ │ ├── Widgets
│ │ └── __tests__
│ │ └── routes.js // routes defined in root
│ ├── redux
│ │ ├── init.js
│ │ ├── middleware
│ │ │ └── clientMiddleware.js // etc
│ │ └── modules // (action/creator/reducer/selector bundles)
│ │ ├── auth.js
│ │ ├── counter.js
│ │ ├── reducer.js
│ │ ├── info.js
│ │ └── widgets.js
│ ├── server
│ │ ├── middleware
│ │ └── actions // proxy to separate REST api...
│ └── utils
│ │ ├── validationUtility.js // utility only (component-level definitions inside respective dir)
│ └── createDevToolsWindow.js // etc
├── static
│ ├── dist
│ └── images
└── webpack