Presentational and Container Components
https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
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. This article explains it well, but I want to add a few more points.
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.
My presentational components:
- Are concerned with how things look.
- May contain both presentational and container components** inside, and usually have some DOM markup and styles of their own.
- Often allow containment via this.props.children.
- Have no dependencies on the rest of the app, such as Flux actions or stores.
- 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 written as functional components unless they need state, lifecycle hooks, or performance optimizations.
- Examples: Page, Sidebar, Story, UserInfo, List.
My container components:
- Are concerned with how things work.
- May contain both presentational and container components** inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
- Provide the data and behavior to presentational or other container components.
- Call Flux actions and provide these as callbacks to the presentational components.
- Are often stateful, as they tend to serve as data sources.
- 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: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.
I put them in different folders to make this distinction clear.
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.
- 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.
Remember, components don’t have to emit DOM. They only need to provide composition boundaries between UI concerns.
Take advantage of that.
When to Introduce Containers?
I suggest you to start building your app with just presentational components first. Eventually you’ll realize that you are passing too many props down the intermediate components. When you notice that some components don’t use the props they receive but merely forward them down and you have to rewire all those intermediate components any time the children need more data, it’s a good time to introduce some container components. This way you can get the data and the behavior props to the leaf components without burdening the unrelated components in the middle of the tree.
This is an ongoing process of refactoring so don’t try to get it right the first time. As you experiment with this pattern, you will develop an intuitive sense for when it’s time to extract some containers, just like you know when it’s time to extract a function. My free Redux Egghead series might help you with that too!
Other Dichotomies
It’s important that you understand that the distinction between the presentational components and the containers is not a technical one. Rather, it is a distinction in their purpose.
By contrast, here are a few related (but different!) technical distinctions:
- Stateful and Stateless. Some components use React setState() method and some don’t. While container components tend to be stateful and presentational components tend to be stateless, this is not a hard rule. Presentational components can be stateful, and containers can be stateless too.
- Classes and Functions. Since React 0.14, components can be declared both as classes and as functions. Functional components are simpler to define but they lack certain features currently available only to class components. Some of these restrictions may go away in the future but they exist today. Because functional components are easier to understand, I suggest you to use them unless you need state, lifecycle hooks, or performance optimizations, which are only available to the class components at this time.
- Pure and Impure. People say that a component is pure if it is guaranteed to return the same result given the same props and state. Pure components can be defined both as classes and functions, and can be both stateful and stateless. Another important aspect of pure components is that they don’t rely on deep mutations in props or state, so their rendering performance can be optimized by a shallow comparison in their shouldComponentUpdate() hook. Currently only classes can define shouldComponentUpdate() but that may change in the future.
Both presentational components and containers can fall into either of those buckets. In my experience, presentational components tend to be stateless pure functions, and containers tend to be stateful pure classes. However this is not a rule but an observation, and I’ve seen the exact opposite cases that made sense in specific circumstances.
Don’t take the presentational and container component separation as a dogma. Sometimes it doesn’t matter or it’s hard to draw the line. If you feel unsure about whether a specific component should be presentational or a container, it might be too early to decide. Don’t sweat it!
Example
This gist by Michael Chan pretty much nails it.
Further Reading
- Getting Started with Redux
- Mixins are Dead, Long Live Composition
- Container Components
- Atomic Web Design
- Building the Facebook News Feed with Relay
Footnotes
* In an earlier version of this article I called them “smart” and “dumb” components but this was overly harsh to the presentational components and, most importantly, didn’t really explain the difference in their purpose. I enjoy the new terms much better, and I hope that you do too!
** In an earlier version of this article I claimed that presentational components should only contain other presentational components. I no longer think this is the case. Whether a component is a presentational component or a container is its implementation detail. You should be able to replace a presentational component with a container without modifying any of the call sites. Therefore, both presentational and container components can contain other presentational or container components just fine.
Presentational and Container Components的更多相关文章
- [Redux] Extracting Container Components (FilterLink)
Learn how to avoid the boilerplate of passing the props down the intermediate components by introduc ...
- (翻译)React Container Components
原文:Container Components Container Components 在 React 模式上对我的代码有最深远影响的一个模式叫 container component 模式. 在 ...
- (翻译) Container Components
react.js javascript 这篇文章翻译自Medium的一篇文章:Container Components 选择这篇文章翻译的原因是,在刚接触React的时候,这篇文章很好的指引我了解 ...
- [Redux] Extracting Container Components -- Complete
Clean TodoApp Component, it doesn't need to receive any props from the top level component: const To ...
- [Redux] Redux: Extracting Container Components -- AddTodo
Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...
- [Redux] Extracting Container Components -- VisibleTodoList
Code to be refacted: const TodoList = ({ todos, onTodoClick }) => ( <ul> {todos.map(todo =& ...
- 【原创】Redux 卍解
Redux 卍解 Redux - Flux设计模式的又一种实现形式. 说起Flux,笔者之前,曾写过一篇<ReFlux细说>的文章,重点对比讲述了Flux的另外两种实现形式:『Facebo ...
- React + Redux 入坑指南
Redux 原理 1. 单一数据源 all states ==>Store 随着组件的复杂度上升(包括交互逻辑和业务逻辑),数据来源逐渐混乱,导致组件内部数据调用十分复杂,会产生数据冗余或者混用 ...
- [react] 细数 React 的原罪
Props & onChange 的原罪 .「props & onChange 接口规范」它不是一个典型的「程序接口规范」. 当你拿到一个可视组件的 ref,却没有类似 setProp ...
随机推荐
- mysql8.x开启远程登录
mysql8.x密码的认证方式变了,需要修改远程认证方式 问题描述 Connection to lab-130-mysql failed.Unable to load authentication p ...
- Ubuntu x86-64汇编(4) 数值操作指令
整数乘法指令 Integer Multiplication 对于有符号数的乘法有特殊的规则, 因此无符号数乘法和有符号数乘法对应着不同的指令mul和imul. 乘法会产生两倍尺寸的数值结果, 即两个n ...
- java开发微信模板消息推送
发布时间:2018-12-12 技术:springboot+maven 概述 该demo主要涉及微信模板消息推送功能, 详细 代码下载:http://www.demodashi.com/dem ...
- Ubuntu系统下添加程序启动器
Ubuntu系统上安装的软件,有的会自动创建快捷方式,在程序中可以搜索到,而有的安装后不会在应用程序中出现,如Eclipse.Spring Tool Suite或是绿色软件等,那么怎么手动创建快捷方式 ...
- Debug 路漫漫-02
重现标准 BTL Model ,using MATLAB: 1. 错误使用 cat要串联的数组的维度不一致.出错 cell2mat (line 83) m{n} = cat(1,c{:,n}); —— ...
- 是否只查看安全传送的网页内容? 去掉 IE弹出窗口
选择IE工具intemt选项,在选项卡里选择安全,然后在安全选项卡里点自定义级别,在设置里找到‘其他’这个分类,在次分类下找到‘显示混合内容’选择‘启用’然后保存退出就OK了,当然楼上几位说安全问题, ...
- iOS 如何写出更加严谨的应用
本文旨在介绍一些能够帮助大家避开一些开发误区的经验. 一: 在开发中,经常能够遇到共用同一个界面的情况,一般情况下,我们会根据传入的model去做数据处理和保存. 当然如果不存在复用的情况下,根本不需 ...
- Kickstart无人值守安装[转载]
导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装. 常规的办法有什么? 光盘安装系统===>一个服务器DV ...
- ant执行jar包中的main方法
<project name= "myproject" basedir= "." default="main"> <p ...
- 树莓派进阶之路 (018) - raspberryPi摄像头命令行软件raspistill帮助文档
文档原文:https://www.raspberrypi.org/app/uploads/2013/07/RaspiCam-Documentation.pdf 作用 在指定的时间运行摄像头,而且如果需 ...