A well-thought structure is helpful for the maintainability of the code.
It also helps to avoid some common anti-patterns.
A redux application is not necessary a big thing, it can also be a component that is complex enough to require redux.
There are the only 2 rules to comply with, so it is not painful to always have them in mind while developing.
In order to have a scalable application, use a modular organisation by opposition with a type organisation:
type organisation:
actions/
spotify-search.js
twitter-log.js
components/
spotify-search/
spotify-search.js
twitter-log/
twitter-log.js
constants/
spotify-search.js
twitter-log.js
reducers/
spotify-search.js
twitter-log.js
selectors/
spotify-search.js
twitter-log.js
index.js
modular organisation:
spotify-search/
actions.js
components/
constants.js
reducer.js
selectors.js
index.js
twitter-log/
...
If you want to work on a feature, you don't have to browse the entire application to get all files related to this feature.
Sometimes it won't be as obvious as it sounds.
It's the opposite of the monolithic approach and offers a way to avoid it, working on a feature should only involve 1 module folder.
If more than 1 module folder is involved, either the code smells or the task is too big.
The modular organisation also eases the following rule.
The complexity of an application can have many reasons, one of them is the interleaving of modules (which is commonly called the spaghetti code).
In other words, coupling things together make it complicated to reason about 1 specific thing and not be forced to deal about all other things.
A simple task become quickly a hard one as the application grows.
bad (interleaving):
// in twitter-log
import reducer from '../spotify-search';
import SpotifyView from '../spotify-search/components/spotify-search-view';
This code implies that within the twitter-log module, i know how the spotify-search module is made.
If spotify-search is updated, then you have to look for all dependent modules and update them accordingly.
Interleaving is a structural coupling, coupling is evil.
good (rely on module API):
// in twitter-log
import spotifySearch from '../spotify-search';
const { reducer, SpotifyView } = spotifySearch;
Decoupling modules allows to freely update them without breaking dependent modules, as soon as the API is not changed.
Instead of reaching inside other modules, we define and maintain contracts between them.
The last thing to know is how and where I define the API of a module:
// in index.js
// the module knows its structure
import reducer from './reducer';
import SpotifyView from './components/spotify-search-view';
// public API of the module
export { reducer, SpotifyView };