There’s a simple pattern I find immensely useful when writing React applications. If you’ve been doing React for a while, you have probably already discovered it.
You’ll find your components much easier to reuse and reason about if you divide them into two categories. I call them Container and Presentational components but I also heard Fat and Skinny, Smart and Dumb, Stateful and Pure, Screens and Components, etc. These all are not exactly the same, but the core idea is similar.
|Presentational (Smart)||Containers (Dumb)|
|Are concerned with how things look.||Are concerned with how things work.|
|May contain both presentational and container components inside. Usually have some DOM markup and styles of their own.||May contain both presentational and container components inside. Usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.|
|Often allow containment via this.props.children||Provide the data and behavior to presentational or other container components.|
|Have no dependencies on the rest of the app, such as Flux actions or stores.||Call Flux actions and provide these as callbacks to the presentational components.|
|Don’t specify how the data is loaded or mutated. Receive data and callbacks exclusively via props. Rarely have their own state (when they do, it’s UI state rather than data)||Are often stateful, as they tend to serve as data sources|
|Are written as functional components unless they need state, lifecycle hooks, or performance optimizations.||Are usually generated using higher order components such as connect() from React Redux, createContainer() from Relay, or Container.create() from Flux Utils, rather than written by hand.|
|Examples: Page, Sidebar, Story, UserInfo, List||Examples:UserPage, FollowersSidebar, StoryContainer, FollowedUserList.|
Benefits of This Approach
- Better separation of concerns. You understand your app and your UI better by writing components this way.
- Better reusability. You can use the same presentational component with completely different state sources, and turn those into separate container components that can be further reused.
- Presentational components are essentially your app’s “palette”. You can put them on a single page and let the designer tweak all their variations without touching the app’s logic.
You can run screenshot regression tests on that page.
- Less duplication of code. This forces you to extract “layout components” such as Sidebar, Page, ContextMenu and use this.props.children instead of duplicating the same markup and layout in several container components.
Thus, structuring your React components in a proper manner will go a long way in building extensible, reusable and scalable software. Also, there's the aspect of reducing the complexity of a large codebase into more of a microservice-like-architecture for better maintenance and developer experience because, at the end of the day, a project is only as good as the energy of the team of developers working on it !!