react的setState是同步还是异步

直接上结论:

在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对事物做了专门的处理。

你可能感兴趣的:(react的setState是同步还是异步)