将初始状态作为一个道具传递给一个组件是一种反模式,因为getInitialState 方法只在组件第一次渲染时被调用,之后就不再调用。这意味着,如果你重新渲染父类,同时传递一个不同的值作为道具,该组件将不会更新用户界面,因为它将保持第一次渲染时的状态。这将使应用程序非常容易出错。
解决方案?让组件成为无状态。它们更容易测试,因为它们是基于输入来渲染输出的。让父组件包含传入的数据作为它自己的状态,然后如果状态改变,它就重新渲染它的子组件,同时通过props ,传入它们需要的一切。
这在React中是什么样子的?
父组件(或所谓的 "控制器视图")将通过ajax调用获得所有的数据(使用flux模式),并将其放入getInitialState 。
另一个解决方案是向子组件发送 "处理程序",然后这些父组件的处理程序一旦被子组件调用,就会进行setState操作,从而对UI进行重新渲染。StackOverflow上有一个很好的例子:reactjs-two-components-communicating。
最好的解决方案是有一个 "容器 "或 "ControllerView "将处理程序传递给子组件...
var ListContainer = React.createClass({
handleFilterUpdate(filterValue){
this.setState({
nameFilter: filterValue
});
} ,
render(){
return (
<div>
<Filters updateFilter={this.handleFilterUpdate}/>
<List items={displayedItems}/>
</div>
);
}
});
var Filters = React.createClass({
handleFilterChange(){
var value = this.refs.filterInput.getDOMNode().value;
this.props.updateFilter(value);
},
render(){
return (
<div><input ... ref="filterInput" onChange={this.handleFilterChange} /></div>
)
}
});
// this is not good
getInitialState: function(){
return {
text: this.props.text
}
}
这样做的另一个问题是,传递text 属性的父代可能期望它包含最新的值,但它没有。
在getInitialState ,使用从父类传递下来的道具来生成状态,往往会导致 "真实来源 "的重复,而真实数据就在那里。