震惊! React中三个方法获取setState更新之后的state !其中一个竟用到Promise!

问题的诞生

React的setState方法是个异步方法.所以,若是在setState之后立即访问state,往往是不能得到更新之后的state值的.

试看如下代码:

class Orz extends Component{
  constructor(props){
    super(props);
    this.state = {
      value:1,
    }
  }
  componentDidMount(){
    this.setState({value:this.state.value+1});
    console.log(this.state.value);
    this.setState({value:this.state.value+1});
    console.log(this.state.value);
    this.setState({value:this.state.value+1});
    console.log(this.state.value);
    this.setState({value:this.state.value+1});
    console.log(this.state.value);
  }
  render(){
    return (
      <div></div>
    );
  }
}

挂载这个标签之后,console里输出:

1
1
1
1

,而并不是我们想象中的

2
3
4
5

.

为了解决这个问题,有三个办法.

笔者推荐第一种方法.若是您觉得第一种方法太naïve,可以采用使用了Promise的第三种方法.

  1. 利用setTimeout.

代码如下:

  componentDidMount(){
    setTimeout(() => {
      this.setState({value:this.state.value+1});
      console.log(this.state.value);
      this.setState({value:this.state.value+1});
      console.log(this.state.value);
      this.setState({value:this.state.value+1});
      console.log(this.state.value);
      this.setState({value:this.state.value+1});
      console.log(this.state.value);
    },0)
  }

就是把整片代码全部包在setTimeout里面.这样react就会自动强制更新.

  1. 利用setState的回调函数

参考官方文档.

setState(updater, [callback])

其中,updator是一个函数,如下:

(prevState, props) => stateChange

每当state得到更新,就会调用callback函数 .

代码可以是这样:

this.setState(({value}=>{
	value:value+1
}),()=>{
	console.log(this.state.value);
});

3.利用Promise,进一步封装方法2

代码由el老师给出.

  setStatePromise(updator) {
    return new Promise( function (resolve,reject){
      this.setState(updator,resolve);
    }.bind(this))
  }
  componentDidMount(){
    this.setStatePromise(({value}) => ({
      value:value+1
    })).then(() => {
      console.log(this.state.value);
    });
  }

这种方法,多连几个then也就成了地狱.

el老师说:区别在于走楼梯下地狱还是坐电梯下地狱.

第2种和第3种方法,其实并不能从根本上解决问题.

callback hell还是Promise hell或者是最简单的setTimeout, 或者是干脆放弃React呢?请君自行选择.

三种方法背后的原理

"深入理解React技术栈"这本书中关于setState的机制有详细描述.

笔者简录如下:

setState是一个异步方法.由队列实现.

它有Batch模式(批量更新模式),和普通模式.

普通模式下,setState能够即时更新state.

Batch模式下,setState会将队列中的state进行合并,然后就会出各种状况.

setTimeout就是一个强制使用普通模式的方法.

也可以去看看这本书作者(陈屹)管理的知乎专栏pure render. 问题引入代码改编自这本书上的例子.

(标题只是为了搞笑)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值