React文档指出render
函数应该 纯 ,这意味着它不应该使用this.setState
。但是,我相信当状态依赖于'remote'即来自ajax调用的结果。唯一的解决方案是setState()
函数内的render
在我的情况下。我们的用户可以登录。登录后,我们还需要检查用户的访问权限(ajax调用)来决定如何显示页面。代码是这样的
React.createClass({
render:function(){
if(this.state.user.login)
{
//do not call it twice
if(this.state.callAjax)
{
var self=this
$.ajax{
success:function(result)
{
if(result==a)
{self.setState({callAjax:false,hasAccess:a})}
if(result==b)
{self.setState({callAjax:false,hasAccess:b})}
}
}
}
if(this.state.hasAccess==a) return <Page />
else if(this.state.hasAccess==a) return <AnotherPage />
else return <LoadingPage />
}
else
{
return <div>
<button onClick:{
function(){this.setState({user.login:true})}
}>
LOGIN
</button>
</div>
}
}
})
ajax调用无法显示在componentDidMount
中,因为当用户单击LOGIN按钮时,页面将被重新呈现并且还需要调用ajax。因此,我认为setState
的唯一位置在render
内1}}违反React原则的函数
有更好的解决方案吗?提前致谢
答案 0 :(得分:16)
setState
总是保持纯洁。在那里做一些有效的事情是非常糟糕的做法,并且调用React.createClass({
getInitialState: function() {
return {
busy: false, // waiting for the ajax request
hasAccess: null, // what the user has access to
/**
* Our three states are modeled with this data:
*
* Pending: busy === true
* Has Access: hasAccess !== null
* Initial/Default: busy === false, hasAccess === null
*/
};
},
handleButtonClick: function() {
if (this.state.busy) return;
this.setState({ busy: true }); // we're waiting for ajax now
this._checkAuthorization();
},
_checkAuthorization: function() {
$.ajax({
// ...,
success: this._handleAjaxResult
});
},
_handleAjaxResult: function(result) {
if(result === a) {
this.setState({ hasAccess: a })
} else if(result ===b ) {
this.setState({ hasAccess: b })
}
},
render: function() {
// handle each of our possible states
if (this.state.busy) { // the pending state
return <LoadingPage />;
} else if (this.state.hasAccess) { // has access to something
return this._getPage(this.state.hasAccess);
} else {
return <button onClick={this.handleButtonClick}>LOGIN</button>;
}
},
_getPage: function(access) {
switch (access) {
case a:
return <Page />;
case b:
return <AnotherPage />;
default:
return <SomeDefaultPage />;
}
}
});
是一个大红旗;在这样一个简单的例子中它可以正常运行,但它是通向高度不可维护的组件的道路,而且它只能起作用,因为副作用是异步的。
相反,请考虑组件可以处于的各种状态 - 就像您在建模状态机一样(事实证明,您是):
使用组件的状态对其进行建模,你就可以了。
<li><%# Eval("Alert") %></li>