Redux FAQ: Code Structure
- What should my file structure look like? How should I group my action creators and reducers in my project? Where should my selectors go?
- Why should I use action creators?
Code Structure
- Rails-style: separate folders for “actions”, “constants”, “reducers”, “containers”, and “components”
- Domain-style: separate folders per feature or domain, possibly with sub-folders per file type
- “Ducks”: similar to domain style, but explicitly tying together actions and reducers, often by defining them in the same file
It's generally suggested that selectors are defined alongside reducers and exported, and then reused elsewhere (such as in functions, in async action creators, or sagas) to colocate all the code that knows about the actual shape of the state tree in the reducer files.
While it ultimately doesn't matter how you lay out your code on disk, it's important to remember that actions and reducers shouldn't be considered in isolation. It's entirely possible (and encouraged) for a reducer defined in one folder to respond to an action defined in another folder.
Further information
Documentation
How to Scale React Applications (accompanying talk: )
- Redux Best Practices
- A Better File Structure for React/Redux Applications
- Four Strategies for Organizing Code
- Redux Reducer/Selector Asymmetry
- My journey towards a maintainable project structure for React/Redux
Discussions- React Boilerplate #27: Application Structure
- Twitter: There is no ultimate file structure for Redux
There's no single clear answer to exactly what pieces of logic should go in a reducer or an action creator. Some developers prefer to have “fat” action creators, with “thin” reducers that simply take the data in an action and blindly merge it into the corresponding state. Others try to emphasize keeping actions as small as possible, and minimize the usage of in an action creator. (For purposes of this question, other async approaches such as sagas and observables fall in the "action creator" category.)
This comment sums up the dichotomy nicely:
Find the balance between these two extremes, and you will master Redux.
Further information
Articles
- How to Scale React Applications
DiscussionsHow putting too much logic in action creators could affect debugging
- #1165: Where to put business logic / validation?
- Stack Overflow: Accessing Redux state in an action creator?
- Twitter: Moving away from unclear terminology…
Redux does not require action creators. You are free to create actions in any way that is best for you, including simply passing an object literal to . Action creators emerged from the and have been adopted by the Redux community because they offer several benefits.
Action creators are testable. The correctness of an inline action must be verified manually. Like any function, tests for an action creator can be written once and run automatically.
Action creators are easier to document. The action creator's parameters enumerate the action's dependencies. And centralization of the action definition provides a convenient place for documentation comments. When actions are written inline, this information is harder to capture and communicate.
Action creators are a more powerful abstraction. Creating an action often involves transforming data or making AJAX requests. Action creators provide a uniform interface to this varied logic. This abstraction frees a component to dispatch an action without being complicated by the details of that action's creation.
Further information
Articles
Middleware are the right place for persistent connections like websockets in a Redux app, for several reasons:
- Middleware exist for the lifetime of the application
- Like with the store itself, you probably only need a single instance of a given connection that the whole app can use
- Middleware can see all dispatched actions and dispatch actions themselves. This means a middleware can take dispatched actions and turn those into messages sent over the websocket, and dispatch new actions when a message is received over the websocket.
- A websocket connection instance isn't serializable, so
See this example that shows how a socket middleware might dispatch and respond to Redux actions.
Libraries