[react]关于容器组件
本文译自Container Components。
React的许多设计模式都给我的代码带来了深远的影响,而容器组件模式就是其中之一。
在React.js大会上,Jason Bonta介绍了他们在Facebook是如何构建高性能组件的,其中包含了这段关于容器组件的精髓.
其思想很简单:
容器负责获取数据,然后渲染到相应的子组件上。完毕。
“相应”的意思是同名的组件,例如:
StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList
明白了吧。
为什么要用容器组件?
假设你有个组件负责显示评论。如果没有容器组件,那就得把所有代码都写到一起:
// CommentList.js
class CommentList extends React.Component {
constructor() {
super();
this.state = { comments: [] }
}
componentDidMount() {
$.ajax({
url: "/my-comments.json",
dataType: 'json',
success: function(comments) {
this.setState({comments: comments});
}.bind(this)
});
}
render() {
return <ul> {this.state.comments.map(renderComment)} </ul>;
}
renderComment({body, author}) {
return <li>{body}—{author}</li>;
}
}
该组件要负责获取数据,还得负责显示数据。这样其实没什么错误,但却丧失了React的几点好处。
可复用性
CommentList
只能在环境完全一致的时候才能复用。
数据结构
组件应该声明它所需要的数据,PropTypes就是用来干这个的。
但是,尽管上面的组件知道自己需要什么数据结构,但却没办法声明这种需求。因此,服务器端的json结构发生变化,该组件就会悄无声息地停止工作。
用容器重新写一遍
首先,将所有获取数据的操作都写进容器组件。
// CommentListContainer.js
class CommentListContainer extends React.Component {
constructor() {
super();
this.state = { comments: [] }
}
componentDidMount() {
$.ajax({
url: "/my-comments.json",
dataType: 'json',
success: function(comments) {
this.setState({comments: comments});
}.bind(this)
});
}
render() {
return <CommentList comments={this.state.comments} />;
}
}
然后改一下CommentList
,接受comments
属性。
// CommentList.js
class CommentList extends React.Component {
constructor(props) {
super(props);
}
render() {
return <ul> {this.props.comments.map(renderComment)} </ul>;
}
renderComment({body, author}) {
return <li>{body}—{author}</li>;
}
}
这样做有什么好处?
实际上好处多多:
- 数据获取和渲染操作完全分离
CommentList
组件可复用CommentList
可以设置PropTypes
,这样出错时会报告错误
我很喜欢容器组件。它深深地影响了我的React代码,让我的组件更易读。试试看,并且推荐看一下Jason的演讲。很赞的!