Container Components
在 React 模式上對我的代碼有最深遠影響的一個模式叫 container component 模式。
在 React.js Conf 上,Jason Bonta 和我們講了他們在Facebook上是如何建立高性能組件(High Performance Components)。Nestled 在這個演講中講的就是 this gem about container components。
這個概念很簡單:
一個 container 只是做數據拉取然后渲染與它的 corresponding 子組件。就是這樣。
“Corresponding” 意味着分享同一個名稱的組件,例如:
StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList
這就是其中的概念。
Why containers?
比如你有一個用於展示評論的組件。你並不知道有關 container 組件。所以,你會將所有東西都放在一個地方。
// 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});
}.bind(this)
});
}
render(){
return <ul> {this.state.comments.map(renderComponent)} </ul>;
}
renderComponent({body, author}){
return <li> {body}-{author} </li>;
}
}
你的組件就是用於拉取數據並展示它。這並沒有什么"錯誤",但是你卻錯過了一些React的優點。
可復用性
CommentList組件除了在同一精確的條件情況下才能復用。
數據結構
你希望的組件應該規定他們需要的數據類型的預期。PropTypes正是干這個的。
我們的組件對數據結構要求很高但是沒有辦法說出這些要求。如果json的接口數據改變了,這個組件會不做出任何提示出錯。(其實想說的就是,無法好好利用PropTypes來把控數據結構是否正確)
再來一次。這一次加上container
首先,讓我們將數據拉取的功能移到 container 組件上。
// 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} />;
}
}
現在,我們將comments作為CommentList的prop重制一遍。
// 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並且一旦出錯便會提示。
我是一個 container components 的大粉絲。他們讓我的 React game 進步了很多,並且使我的組件更容易去閱讀。嘗試一下他們,並看一下Jason的演講。太棒了!
Carry on, nerds.
