我使用react-react进行反应。在使用IndexRoute上的onEnter Asynchronous挂钩检查身份验证后,将呈现App组件。应用程序组件具有初始状态auth,在呈现时设置为undefined。 auth状态被传递给Navbar组件作为prop,它将用于决定是否显示登录,注册和注销链接。
当App组件完成呈现时,componentDidMount()
进行ajax调用以再次检查用户是否经过身份验证。在回应时它会改变状态。在从ajax请求状态更改后,我将日志状态更改为控制台,this.setState()
方法不会更改状态,但仍会以某种方式触发Navbar组件上的componentWillReceiveProps()方法,并且this.props.auth
值仍未定义。< / p>
// Checks Authentication Asynchronously
isAuthenticated(nextState, replace, callback) {
$.ajax({
type : 'GET',
url : '/auth',
success : function(res){
if(!res){
callback(replace({ pathname: '/login', query: { auth: 'false' } }));
}else{
callback();
}
}
});
};
// routes
var routes = (
<Router history={browserHistory}>
<Route path="/" component={require('./components/app')}>
<IndexRoute component={require('./components/dashboard/index')} onEnter={Auth.isAuthenticated}/>
<Route path="/register"
component={require('./components/authentication/register')}
onEnter={Auth.isNotAuthenticated} />
<Route path="/login"
component={require('./components/authentication/login')}
onEnter={Auth.isNotAuthenticated}/>
<Route path="*"
component={require('./components/404/404')}/>
</Route>
</Router>
);
// App
const App = React.createClass({
getInitialState(){
return {
auth : undefined
}
},
componentDidMount(){
console.log('App componentDidMount');
this.checkAuth();
},
checkAuth(){
var self = this;
$.ajax({
type : 'GET',
url : '/auth',
success : function(res){
if(res){
self.setState({
auth : true
});
}else{
self.setState({ auth : false});
}
}
});
console.log(this.state.auth);
},
render() {
return(
<div className="appWrapper">
<Navbar auth={this.state.auth}/>
<div className="container">
{this.props.children}
</div>
</div>
);
}
});
// Navbar
var Navbar = React.createClass({
getInitialState(){
return{
user_actions : '' ,
auth : this.props.auth
}
},
componentDidMount(){
console.log('Navbar componentDidMount ', this.props.auth);
this.checkAuthState();
},
componentWillReceiveProps(){
console.log('Navbar componentWillReceiveProps ', this.props.auth);
this.setState({
auth : this.props.auth
});
this.checkAuthState();
},
checkAuthState(){
console.log('Nav Mounted with auth : ', this.state.auth);
if(this.state.auth == undefined){
this.state.user_actions = '';
}
if(!this.state.auth){
this.state.user_actions = <ul className="nav navbar-nav navbar-right">
<li><a href="/login">Login</a></li>
<li><a href="/register">Register</a></li>
</ul>;
this.setState({
user_actions : this.state.user_actions
});
}
if(this.state.auth){
this.state.user_actions = <ul className="nav navbar-nav navbar-right">
<li><a href="/logout">Logout</a></li>
</ul>;
this.setState({
user_actions : this.state.user_actions
});
}
},
render : function(){
return (
<nav className="navbar navbar-default">
<div className="container">
<a href="/" className="navbar-brand">Reactor</a>
{this.state.user_actions}
</div>
</nav>
);
}
});
答案 0 :(得分:21)
首先,我建议你重读React.JS文档,因为有几件事需要注意:
- 不要直接改变
this.state
,而是使用setState
方法。(line: 108, 111, 121, 133, 136, 146)
- 您应该使用state来存储随时间变化的数据,而不是元素。
醇>(line: 111, 121, 136, 146)
TL;博士; 让我们回到问题:
如果您在ajax请求后打印该值,您将无法看到它!原因是:
首先,您使用Ajax执行异步请求并尝试以同步方式查看结果。 JS将首先执行您的console.log
,它仍然包含请求之前的值,然后执行ajax请求回调。这是您的代码块:
$.ajax({ ...,
success: function(res) {
if(res) { self.setState({ auth : true }); }/
...
} // will executed later (after ajax get response)
});
console.log(this.state.auth); // will executed first, this is why it always prints the value as undefined
其次,在设置新状态值后,您无法立即看到更改后的状态值。例如,假设this.state.auth
的值为false
:
this.setState({ auth: true});
console.log(this.state.auth); // will print false, instead of true as your new value
您可以使用componentWillUpdate(nextProps, nextState)
方法查看新的州值。您可以通过以下链接了解此信息:React.JS Component Specs and Lifecycle
这意味着您的ajax响应上的setState()
成功更改了您的状态值。证据是Navbar组件接收一个新的道具,它通过App组件发送它(其中auth状态被更改),这将触发componentWillReceiveProps()
方法。
也许你的代码应该是这样的:
// App
const App = React.createClass({
getInitialState : function(){
return {
auth : false
}
},
componentDidMount : function() {
console.log('App componentDidMount');
this.checkAuth();
},
componentWillUpdate : function(nextProps, nextState) {
//you'll see the changing state value in here
console.log('Your prev auth state: ' + this.state.auth);
console.log('Your next auth state: ' + nextState.auth);
},
checkAuth : function(){
var self = this;
$.ajax({
type : 'GET',
url : '/auth',
success : function(res){
if(res){
self.setState({ auth : true });
}
}
});
},
render : function(){
return(
<div className="appWrapper">
<Navbar auth={this.state.auth}/>
<div className="container">
{this.props.children}
</div>
</div>
);
}
});
// Navbar
// Because the navbar component receive data (this.props.auth) from parent (app) via props, so we're no longer need to assign auth as a state in Navbar component.
const Navbar = React.createClass({
render : function(){
// you're no longer need checkAuthState method
let navItems;
if(!this.props.auth){
navItems = (<ul className="nav navbar-nav navbar-right">
<li><a href="/login">Login</a></li>
<li><a href="/register">Register</a></li>
</ul>);
} else {
navItems = (<ul className="nav navbar-nav navbar-right">
<li><a href="/logout">Logout</a></li>
</ul>);
}
return (
<nav className="navbar navbar-default">
<div className="container">
<a href="/" className="navbar-brand">Reactor</a>
{ navItems }
</div>
</nav>
);
}
});
希望它有所帮助!
答案 1 :(得分:1)
在ajax范围内。它无法访问反应状态。作为替代方案,您可以将模块中的其他方法称为ajax成功调用,然后在那里更新状态。 按照这个例子。
var reactModule = React.createClass({
getInitialState:function(){
},
render: function() {
return (
<div>
content
</div>
);
},
componentDidMount: function() {
var ajaxSuccess=this.ajaxSuccess;
$.ajax({
type: "POST",
url: $api_url + 'index.php/app/icon1_update',
dataType: "text",
data:fd,
contentType: false,
processData: false,
success: ajaxSuccess
});
},
ajaxSuccess:function(e){
//e is the result. update state here.
}
});
答案 2 :(得分:0)
请查看componentWillReceiveProps的文档:
componentWillReceiveProps(
object nextProps
)
https://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops
当您的属性发生变化时,访问属性“nextProps”。否则,您将访问旧属性。
作为一个小提示: 在render方法中包含checkAuthState()代码,而不是在componentDidMount方法中,因为您可以避免使用setState调用。
答案 3 :(得分:0)
只需使用箭头功能即可访问“此”:
success: () => {
this.setState({ data: value })
}