React 中执行 setState 时怎么保证你取到的上一次state是正确的?

setState 是 React 用于管理状态的一个特殊函数,我们在 React 中会经常使用到它,下面的场景你一定遇到过:

export class Todo extends React.Component{
  ... 
  increaseScore () {
    this.setState({count : this.state.count + 1});
    this.setState({count : this.state.count + 1});
  }
  ...
}

上面这段代码, increaseScore函数中希望将 count 这个状态的值在原来的基础上加1再加1,但是实际情况其实并不想你预期的那样,如果你在控制台把count的值打出来,会发现它只增加了1!

为什么呢?

setState 是异步的

setState 是异步的
看一下这个例子

class BadCounter extends React.Component{
  constructor(props){
    super(props);
    this.state = {count : 0} 
  }
  incrementCount=()=>{
    this.setState({count : this.state.count + 1}) 
    this.setState({count : this.state.count + 1})
  }
  render(){
    return <div>
              <button onClick={this.incrementCount}>+2</button>
              <div>{this.state.count}</div>
          </div>
  }
}
 
class GoodCounter extends React.Component{
  constructor(props){
    super(props);
    this.state = {count : 0} 
  }
  incrementCount=()=>{
   this.setState((prevState, props) => ({
      count: prevState.count + 1
    }));
   this.setState((prevState, props) => ({
      count: prevState.count + 1
    }));
  }
  render(){
    return <div>
              <button onClick={this.incrementCount}>+2</button>
              <div>{this.state.count}</div>
          </div>
  }
}

在这个demo中,上下两个计数器都是希望实现点击后数+2,但是实际效果如下,只有第二个计数器达到了我们的预期

结合代码可以发现两个计数器的区别给setState 传递的参数不一样

// 在错误示例中
this.setState({count : this.state.count + 1}) 
this.setState({count : this.state.count + 1}) 
 
// 在正确示例中
this.setState((prevState, props) => ({
  count: prevState.count + 1
}))
this.setState((prevState, props) => ({
  count: prevState.count + 1
}))

查阅资料发现,在多次调用setState()时,React 并不会同步处理这些setState()函数,而是做了一个“批处理”——如果使用对象作为参数传递给setState,React 会合并这些对象。

而同样的情况下,当你给setState()传入一个函数时,这些函数将被放进一个队列,然后按调用顺序执行。

这里是react的核心成员 Dan Abramov 对 setState 为什么是异步的解释

总结:

连续多次执行 setState 操作的情况是很常见的,下一次你如果在 setState 时需要用到上一次state要切记,在 setState 中利用函数操作来取得上一次的 state 值才是正确的做法!

转载地址: React 中执行 setState 时怎么保证你取到的上一次state是正确的?_Missing___的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值