好的,首先,您提到您的组件之外的第三方可能会调用cmp.setState()?这是一个巨大的反应,不。一个组件应该只调用它自己的 setState 函数——外部的任何东西都不能访问它。
另外要记住的是,如果您尝试再次更改状态以响应状态更改 - 这意味着您做错了什么。
当您以这种方式构建事物时,它会使您的问题变得比实际需要的困难得多。原因是如果您接受没有任何外部可以设置组件的状态 - 那么基本上您唯一的选择就是允许外部事物更新组件的道具 - 然后在组件内部对它们做出反应。这简化了问题。
因此,例如,您应该考虑让以前调用 cmp.setState() 的任何外部事物再次在您的组件上调用 React.renderComponent,并提供新的 prop 或 prop 值,例如将 showAdvanced 设置为 true .然后,您的组件可以在 componentWillReceiveProps 中对此做出反应并相应地设置其状态。下面是一段代码示例:
var MyComponent = React.createClass({
getInitialState: function() {
return {
showAdvanced: this.props.showAdvanced || false
}
},
componentWillReceiveProps: function(nextProps) {
if (typeof nextProps.showAdvanced === 'boolean') {
this.setState({
showAdvanced: nextProps.showAdvanced
})
}
},
toggleAdvancedClickHandler: function(e) {
this.setState({
showAdvanced: !this.state.showAdvanced
})
},
render: function() {
return (
<div>
<div>Basic stuff</div>
<div>
<button onClick={this.toggleAdvancedClickHandler}>
{(this.state.showAdvanced ? 'Hide' : 'Show') + ' Advanced'}
</button>
</div>
<div style={{display: this.state.showAdvanced ? 'block' : 'none'}}>
Advanced Stuff
</div>
</div>
);
}
});
所以当你第一次调用React.renderComponent(MyComponent({}), elem) 时,组件将被挂载,高级 div 将被隐藏。如果单击组件内的按钮,它将切换并显示。如果您需要强制组件从组件外部显示高级 div,只需再次调用 render ,如下所示:React.renderComponent(MyComponent({showAdvanced: true}), elem) 它将显示它,而不管内部状态如何。同样,如果您想从外部隐藏它,只需使用 showAdvanced: false 调用它。
对上述代码示例的额外好处是,在 componentWillReceiveProps 内部调用 setState 不会导致另一个渲染周期,因为它会在调用 render 之前捕获并更改状态。请查看此处的文档以获取更多信息:http://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops
不要忘记在已经挂载的组件上再次调用 renderComponent 并不会再次挂载它,它只是告诉 react 更新组件的 props,然后 react 将进行更改、运行生命周期和渲染函数组件并做它的 dom diffing 魔术。