本文梳理了容器与展示组件、高阶组件、render props这三类React组件设计模式
往期回顾:HBaseCon Asia 2019 Track 3 概要回顾
随着 React 的发展,各种组件设计模式层出不穷。React 官方文档也有不少相关文章,但是组织稍显凌乱,本文就组件的设计模式这一角度,从问题出发,为大家梳理了常见的设计模式。看完这篇文章后,你将能得心应手地处理绝大多数 React 组件的使用问题。
开始之前先解释一下什么是设计模式。所谓模式,是指在某些场景下,针对某类问题的某种通用的解决方案。本文所阐述的设计模式并不是编程通用的设计模式,如大家熟悉的单例模式、工厂模式等等。而是在设计 React 组件时的一些解决方案与技巧,包括:
(1)容器与展示组件
(2)高阶组件
(3)render props
(4)context 模式
(5)组合组件
(6)继承
为了更好的理解,你可以将相应源码下载下来查看:(https://github.com/imalextu/learn-react-patterns)
由于内容较多,分两篇进行。上篇先介绍:
(1)容器与展示组件
(2)高阶组件
(3)render props.
一、容器(Container)与展示(Presentational)组件
>>>>
概念介绍
我们先介绍一个较为简单的使用模式,那就是容器组件与展示组件。这种模式还有很多种称呼,如胖组件和瘦组件、有状态组件和无状态组件、聪明组件和傻瓜组件等等。
名称很多,但想要阐述的本质都一样,就是当组件与外部数据进行交互时,我们可以把组件拆为两部分:
容器组件:主要负责同外部数据进行交互(通信),譬如与 Redux 等进行数据绑定、通过普通的 fetch 获取数据等等。
展示组件:只根据自身 state 及接收自父组件的 props 做渲染,并不直接与外部数据源进行沟通。
>>>>
示例
我们来看一个简单的例子。构造一个组件,该组件的作用是获取文本并将其展示出来。
export default class GetText extends React.Component {
state = {
text: null,
}
componentDidMount() {
fetch('https://api.com/',
{ headers: { Accept: 'application/json' } }).then(response => {
return response.json()
}).then(json => {
this.setState({ text: json.joke })
})
}
render() {
return (
<div>
<div>外部获取的数据:{this.state.text}</div>
<div>UI代码</div>
</div>
)
}
}
看到上面 GetText 这个组件,当有和外部数据源进行沟通的逻辑。那么我们就可以把这个组件拆成两部分。
一部分专门负责和外部通信(容器组件),一部分负责UI逻辑(展示组件)。我们来将上面那个例子拆分看看。
容器组件:
export default class GetTextContainer extends React.Component {
state = {
text: null,
}
componentDidMount() {
fetch('https://api.com/',
{ headers: { Accept: 'application/json' } }).then(response => {
return response.json()
}).then(json => {
this.setState({ text: json.joke })
})
}
render() {