According to the readme 'src/components' is labeled "Reusable Presentational Components", same with 'src/containers'. In the example there are 2 routes: home and counter. It is not clear to me why the HomeView has the suffix "View" and is under 'routes/Home/components' while the counter is named simply "Counter" and is among the reusable components. Why is it split into 2 parts: src/components/Counter and routes/Counter ? I can't see the logic.
'src/components' is for Presentational components, not just any component (though I agree the naming of the folder could be improved to something like 'src/presentational').
If you don't see the difference between a Presentational Component and a Container Component, I recommend reading http://redux.js.org/docs/basics/UsageWithReact.html and https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.j9lmjkzhd
For the suffix "View", I have no idea.
For the split between src/components/Counter and routes/Counter:
"But why is the container inside route?", you may ask. My guess is that you could reuse the same Presentational component (src/components/Counter) in several routes, thus have different Counter containers.
Example:
I hope I'm not mistaken, and I hope this helps.
I wonder why the component container logic (e.g. CounterContainer.js and modules/counter.js) is in the src/routes/ path and not e.g. in the src/containers folder. The routes folder is now not just the routes configuration but also the components logic. I find that confusing.
I think the reason for being inside the routes folder may be due to nesting routes. There is a similar folder structure used in react-router examples: https://github.com/reactjs/react-router/tree/master/examples/huge-apps
Many best practices are not obvious in such a trivial example as a counter. I followed the same organizational structure on my more complicated application with nested routes.
@frontalicious-martijn I recommend reading about fractal structure this project is using and also huge-apps example @brianzinn posted. The project structure is correct you are just not thinking in fractals yet :smile:
Yes, I'll start with a structure like this, thanx for the feedback guys.
Related to this I have another question. What if I want to reuse my reducer in another route than the one that it's defined at atm. Is this always bad practice and should restructure my routes so it becomes a subroute when I want to use a certain reducer?
Say that I want to use a counter component at the route '/', I cannot do this because the reducer is defined under the counter route.
@jenyckee - I hope I understand your question correctly - all reducers are available everywhere. when you dispatch an action to the 1 store it goes to all reducers. If you need the state from different reducers in another part of your application, i would try looking at mapStateToProps in the container (ie: CounterContainer). In new route definitions using injectReducer to add another reducer is optional. I would watch the egghead videos on redux, if you haven't already to explain those concepts, if they are not familiar. If you go with sub-routes using their own reducer and container you may need something like { React.cloneElement(this.props.children, {prop1, prop2})} in your sublayout to carry props forward. The learning curve is steep on these concepts. good luck.
@jenyckee - I was also facing this problem .. My idea was to create an "src/modules" folder and place the reducers and related stuff there. In my case I had a Notification logic that is used in multiple place so that I put the reducers under "src/modules/Notification/reducers.js". There are "actions.js" and "actionTypes.js" too in that folder. I put only app and/or route specific stuff into "routes/route-name/modules".
"src/modules/ModuleName" reflects reusability and route-independency.
@janoist1 That is exactly what I ended up doing as well. I added a folder src/modules that contains "core" reducers. I'm wondering now if this is against any bad practice since there is no such folder in this project.
@jenyckee there's nothing wrong with that approach, it's how this project was originally structured. However, it doesn't necessarily scale super well, so @justingreenberg introduced the fractal structure to help prevent people from making the same mistakes. You may find this post helpful.
One thing is still unclear to me. The example connects in the countercontainer the counter component to the counter reducer in the counter route. Like this there is only room for one container and hence one component? What if I want to add another component, IncrementButton, that also needs to be connected to the counter reducer. Where do I connect it?
/* 1. ReactRouter - Create PlainRoute definition object */
export default (store) => ({
path: 'counter',
/* 2. ReactRouter - Invoked when path match (lazy) */
getComponent (nextState, cb) {
/* 3. Webpack (build) - Create split point
4. Webpack (runtime) - Load async chunk with embedded jsonp client */
require.ensure([], (require) => {
/* 5. Webpack (build) - Require all bundle contents */
const Counter = require('./containers/CounterContainer').default
const reducer = require('./modules/counter').default
/* 6. Redux - Use store and helper to add async reducer */
injectReducer(store, { key: 'counter', reducer })
/* 7. ReactRouter - Return component */
cb(null, Counter)
/* 8. Webpack - Provide a name for bundle */
}, 'counter')
}
})
@jenyckee I'm playing around with the project structure for a while and it looks nice to me. You've commented on a route component here. The code injects a given reducer to a route component, not a dumb or smart component which should be in a different folder according to the documentation. So if you want to create a /components/CustomButton folder, create a container in /containers/CustomButton where you connect() your /redux/CustomButton/reducers reducer. And then you can import the container wherever you want. It's not related to any route.
Did I understand your intent correctly?
Most helpful comment
I think the reason for being inside the routes folder may be due to nesting routes. There is a similar folder structure used in react-router examples: https://github.com/reactjs/react-router/tree/master/examples/huge-apps
Many best practices are not obvious in such a trivial example as a counter. I followed the same organizational structure on my more complicated application with nested routes.