bug记录——setState() 的异步操作导致的异常状况

今天在码代码时遇到了一点问题,其实之前应该也是遇到过很多次的,不过当时很少用console来实时检测自己的代码,一直没发现而已。

言归正传——

我在input组件上添加了一个onChange事件来实时更新输入框的值textContent,并通过console输出显示,代码提炼如下:

import React from 'react';
 
class Demo extends React.Component{
  state = {
    textContent: '',
  };
 
  getText= (event) => {
    this.setState({
      textContent : event.target.value,
    })
    console.log(this.state.textContent);
  }

  render(){
    return(
      
) } }

结果问题出现了,每次打印的textContent都是我上一次输入的内容,相当于滞后了一拍,并未达到实时更新的效果。

比如当我输入0,打印出的为空,因为我并未赋初始值,当我继续输入1时,才会出现我上次输入的0。

明明setState已经执行完毕了呀,组件的state应该已经被更新了,为什么还会console出上一轮的值呢。

好奇心旺盛的我立刻去查了查,原来setState()是异步操作,后面的 console.log(this.state.textContent)执行的时候, state还没更新完,所以输出的是之前的值。

原理如下——

setState ()并不是刷新状态树的,它还要合并新旧状态并扫描虚拟DOM树找出受影响的节点,然后去更新节点上的UI部分,这是一件很耗时(相对而言)的事,所以会等一个时机去做批量更新,在这之前state并不会被改变。

简而言之,就是你的数据其实已经改变并被存储在队列中了,只是这个状态还没来得及更新,因为当前事务(transaction)还未走完。

只要脱离了当前事务,狭义点说只要不在当前函数里,你使用的textContent和输入的textContent还是保持一致的,不用担心。

当然了,如果真的不放心,setState也是支持回调的,你可以通过以下代码获取数据:

this.setState({value: event.target.value}, () => console.log(this.state.value))

好啦,今天就到这儿,我们下次再见啦,ciao~ ciao~

你可能感兴趣的:(bug记录——setState() 的异步操作导致的异常状况)