react setState 之同步异步

react setState 之同步异步

问题来源:

在react组件中,每次修改state中的对象后接下来去取修改后的值,有时取到的值是修改前的,有时是修改后的,那setState是同步的还是异步的呢?为什么呢?

讨论1

本次研究就用代码实践来总结体会,找寻答案

import React from "react"
class test extends React.Component {
  constructor(props) {
    this.state = {
      num:0}}
  componentDidMount() {
    this.setState({num: 1, }, (state) => {
        console.log(this.state.num,"setState的回调函数中")
      });
      console.log(this.state.num,"打印")
  }
  render() {
      console.log(this.state.num,"num变化了")
    return (
      <div>     
         <button onClick ={this.handleClick}>点击</button>
      </div>
    ) }}
export default test

在这里插入图片描述
表明在react的生命函数中进行setState是异步的,在生命周期函数中,数据发生改变时,并不能马上得到改变后的值,上面的‘num变化了’一次更新打印了2次,是因为在react中的use strict 严格模式,为了更好的发现程序中的问题,运行了两次。第十行代码执行在dom刷新(每一次state重的数据发生改变时都会出发dom更新,但是因为效能原因,react的数据会一批一批的进行更新,而不是每次更新数据都会进行dom更新)之前,为了在数据更新后就使用更新后的值可以借助 this.setState({num: 1, },cb) 中的cb,利用cb中的取值,我们可以发现在dom进行更新后,取到值,也就是可以暂时得出,

结论1

在生命周期函数中,借助 this.setState({num: 1, },cb) 中的cb可以在dom更新后取到更新后的值。

讨论2

class test extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num:0,
      count:0
    };
  }
  componentDidMount() {
    setTimeout(() => {
        this.setState({count: 5})
        console.log(this.state.count, "定时器") 
    }, 3000)
    new Promise((resolve,reject)=>{
        setTimeout(()=>{
          this.setState({count:6})
          resolve()
        },100)
    }).then(()=>{
          console.log(this.state.count,"primise中")
        })
 document.getElementById("yuansheng").addEventListener("click", this.handleClick2);
  }
  handleClick2 = () =>{
      console.log("点击了原生")
    this.setState({count: 1})
    console.log(this.state.count)
  }
  handleClick = () => {
      console.log("合成点击")
    this.setState({count: 2})
    console.log(this.state.count)
  }
  render() {
    return (
      <div>     
         <button onClick ={this.handleClick}>点击</button>
         <div id="yuansheng">点击2div</div>
      </div>)}}
export default test

在这里插入图片描述

结论2

从上面的运行结果可以看出在定时器和promise这种异步操作中setState可以在代码更新后取到,另外在合成点击(在react中,开发者为了兼容各个平台及其他优点,对原生的事件进行了封装,成为合成事件),并不能立马得到改变后的数据,在利用原生js绑定的原生事件就可以及时的得到改变后的数据。

总结

于是我们可以得到以下结论:
在生命周期函数,合成函数中,不能立马拿到数据原因是,console.log在数据发生改变前执行,为什么发生改变前执行,因为diff算法,虚拟dom一批一批的更新视图层,在执行顺序是,对数据进行setState -> console.log ->算法判断是否更新 -> 数据更新 -> dom更新
而promise,回调函数,原生函数,定时器 这些不受这个算法的影响,它是单独更新视图,不参与他们的一批一批的更新,所以说可以直接取到值

更多前端资料请关注微信公众号:前端从入门到SP
扫码可关注在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值