The question:
What is the most maintainable and recommended best practice for organising containers, components, actions and reducers in a large React/Redux application?
My opinion:
Current trends seem to organise redux collaterals (actions, reducers, sagas...) around the associated container component. e.g.
/src
/components
/...
/contianers
/BookList
actions.js
constants.js
reducer.js
selectors.js
sagas.js
index.js
/BookSingle
actions.js
constants.js
reducer.js
selectors.js
sagas.js
index.js
app.js
routes.js
This works great! Although there seems to be a couple of issues with this design.
The Issues:
When we need to access actions
, selectors
or sagas
from another container it seems an anti-pattern. Let's say we have a global /App
container with a reducer/state that stores information we use over the entire app such as categories and enumerables. Following on from the example above, with a state tree:
{
app: {
taxonomies: {
genres: [genre, genre, genre],
year: [year, year, year],
subject: [subject,subject,subject],
}
}
books: {
entities: {
books: [book, book, book, book],
chapters: [chapter, chapter, chapter],
authors: [author,author,author],
}
},
book: {
entities: {
book: book,
chapters: [chapter, chapter, chapter],
author: author,
}
},
}
If we want to use a selector
from the /App
container within our /BookList
container we need to either recreate it in /BookList/selectors.js
(surely wrong?) OR import it from /App/selectors
(will it always be the EXACT same selector..? no.). Both these appraoches seem sub-optimal to me.
The prime example of this use case is Authentication (ah... auth we do love to hate you) as it is a VERY common "side-effect" model. We often need to access /Auth
sagas, actions and selectors all over the app. We may have the containers /PasswordRecover
, /PasswordReset
, /Login
, /Signup
.... Actually in our app our /Auth
contianer has no actual component at all!
/src
/contianers
/Auth
actions.js
constants.js
reducer.js
selectors.js
sagas.js
Simply containing all the Redux collaterals for the various and often un-related auth containers mentioned above.
BookList
selectors functions, can you show me yourmapStateToProps
function? are you passing thestate
through? or thestate.booklist
– Weary