2

React setState、useState到底是同步的,还是异步的?

setState语法

用法1:

this.setState({
  //  数据更新
})

用法2:

this.setState((state, props) => {
  // 当前组件的state
  // 父级的state
}, () => {
  // 数据更新之后
})

useState语法

用法1:

const [num, setNum] = useState(0);
...
setNum(1);

用法2:

const [num, setNum] = useState(0);
...
setNum(() => {
  // 数据操作
});

setState是同步还是异步?

看一下下面的代码:

import React from 'react';
import { Button } from 'antd-mobile';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }

  onButtonClick() {
    setTimeout(() => {
      this.setState({
        count: 1
      })
      console.log('count00000', this.state.count);
    })

    console.log('count111111', this.state.count);
    setTimeout(() => {
      console.log('count222222', this.state.count);
    })
  }

  render() {
    return (
      <div>
        <Button onClick={this.onButtonClick.bind(this)}>点击</Button>
        <div>
          这个数字就是啊哈哈哈:{this.state.count}
        </div>
      </div>
    )
  }
}

打印结果:
image.png

setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。

合成事件:就是react 在组件中的onClick等都是属于它自定义的合成事件。
原生事件:比如通过addeventListener添加的,dom中的原生事件。

原生事件举例:

state = {
    count:0
};
componentDidMount() {
    document.body.addEventListener('click', this.changeVal, false);
}
changeVal = () => {
    this.setState({
      number: 1
    })
    console.log(this.state.count)
}

useState是同步还是异步?

看一下下面代码:

import React, { useState } from 'react';
import { Button } from 'antd-mobile';
import './index.scss';

const HospitalInfo = () => {
  const [count, setCount] = useState(0);

  const onButtonClick = () => {
    setTimeout(() => {
      setCount(1);
      console.log('count0000', count)
    })

    console.log('count111', count)
    setTimeout(() => {
      console.log('count222', count)
    })
  }

  return (
    <div className="page-hospital-container">
      <Button onClick={onButtonClick}>点击</Button>
      <div>这个数字就是:{count}</div>
    </div>
  );
};

export default HospitalInfo;

image.png
然后,我们发现都没有获取到最新值,说明useState是异步的!

那如何获取最新值呢?

const [count, setCount] = useState(0);
  const countRef = useRef(count);
  countRef.current = count;

  const onButtonClick = () => {
    setTimeout(() => {
      setCount(1);
      console.log('count0000', count)
    })

    console.log('count--Ref11', countRef)


    console.log('count111', count)
    setTimeout(() => {
      console.log('count222', count)
      console.log('count--Ref22', countRef)
    })
  }

看一下结果:
image.png

我们发现在Hooks最近中如果想要获取到最新值,需要在异步+Ref的方式才能获取到!

个人见解,有什么不对的地方,欢迎大神评论区留言😄


起风了
120 声望35 粉丝

北冥有鱼,其名为鲲。鲲之大,不知其几千里也;化而为鸟,其名为鹏。鹏之背,不知其几千里也;怒而飞,其翼若垂天之云。是鸟也,海运则将徙于南冥。南冥者,天池也。