直接上结论:
在react的合成事件中是异步
在原生事件、setTimeout中是同步。
首先,在react中,平常触发state变化的,就是setState,什么时候会触发,就是你onClick、onChange的时候会触发,那么这就是react的合成事件了。
1、合成事件onClick、onChang
我们使用onClick来触发,看下能不能立即拿到变化后的state
import React, { Component } from 'react';
class IndexPage extends Component {
state = {
data: 0,
};
clickTest = () => {
this.setState({
data: this.state.data + 1,
});
console.log('this.state.data', this.state.data); //拿到的是上一次的data值
};
render() {
return (
);
}
}
export default IndexPage;
我们点击按钮触发setState发现不能立即拿到它改变后的值,而是拿到了前面的一次值。说明它在合成事件onClick中是异步的。
2、原生事件、setTimeout
我们修改下代码,把onClick事件去掉,使用原生的监听方法监听点击:
import React, { Component } from 'react';
class IndexPage extends Component {
state = {
data: 0,
};
componentDidMount() {
const _this = this;
const dom = document.getElementById('test');
//添加button的点击监听事件
dom.addEventListener('click', function() {
_this.setState({
data: _this.state.data + 1,
});
console.log('this.state.data', _this.state.data); //此时可以立刻同步拿到变化后的值
});
}
render() {
return (
);
}
}
export default IndexPage;
我们发现,在原生的监听click事件中,能立即在setState后面拿到变化后state的值,所以这是同步的。
接着我们修改代码,使用合成事件onClick,区别是把setState写在setTimeout里面,结果如何:
import React, { Component } from 'react';
class IndexPage extends Component {
state = {
data: 0,
};
clickTest = () => {
setTimeout(() => { //注意这里是setTimeout
this.setState({
data: this.state.data + 1,
});
console.log('this.state.data', this.state.data); //点击后立即拿到了值
}, 0);
};
render() {
return (
);
}
}
export default IndexPage;
如截图结果所示,我们发现,写在setTimeout中的state变化能立即拿到变化值,所以说,这是同步的!
总结:大部分情况下是异步的,因为我们大部分时候都是用react自带的合成事件,因此为了保证能拿到变化后的值,就得使用setState的第二个参数,回调函数
至于为什么会这样,是react对事物做了专门的处理。