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

来源:互联网 发布:淘宝如何清除缓存 编辑:程序博客网 时间:2024/05/16 01:36

问题的诞生

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里输出:

1111

,而并不是我们想象中的

2345

.

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

笔者推荐第一种方法.若是您觉得第一种方法太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就会自动强制更新.

2. 利用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. 问题引入代码改编自这本书上的例子.

(标题只是为了搞笑)

原创粉丝点击