Gui*_*chi 12 asynchronous reactive-programming reactjs
反应文件指出render
函数应该是纯这意味着它不应该使用this.setState
它.但是,我相信,当状态依赖于"远程",即从阿贾克斯call.The唯一的解决办法的结果是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>
}
}
})
Run Code Online (Sandbox Code Playgroud)
ajax调用不能出现,componentDidMount
因为当用户单击LOGIN按钮时,页面被重新呈现并且还需要ajax调用.所以我认为唯一的地方setState
是在render
函数内部违反了React原则
更好的解决方案?提前致谢
Mic*_*ley 21
render
应该永远保持纯洁.在那里做副作用的事情是一种非常糟糕的做法,并且召唤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 />;
}
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
29461 次 |
最近记录: |