React组件的生命周期(16.3以前)和setState API小结

最近看了程墨的几篇文章,对setState这个API有了更加深入的认识,下面总结一下。
先回顾一下React组件的生命周期。

一、组件的生命周期

组件生命周期

在挂载期首先会调用componentWillMount(),然后会接着触发render()渲染到页面,最后调用componentDidMount(),在卸载前会调用componentWillUnmont(),然后卸载组件。
在组件更期时(此处指以props改变为例),首先会从父组件传来props,触发钩子函数(hook)componentWillReceiveProps()(若是state改变不会触发),然后触发shouldComponentUpdate(),如果shouldComponentUpdate()函数返回false,这时候更新过程就被中断了,render函数也不会被调用了,这时候React不会放弃掉对this.state的更新的,所以虽然不调用render,依然会更新this.state。若返回的是true,就会紧接着触发componentWillUpdate(),接着触发render(),更新组件的渲染,最后触发触发componentDidUpdate(),组件卸载和上述流程一样。

二、setState()介绍

引用网上的说法:

React抽象来说,就是一个公式
[图片上传失败...(image-cfb7ee-1531880117865)]

setState是React用来更新state的一个API,用得越多,发现setState()有很多让人入坑的地方:

  1. 使用setState()一般情况下(后面会介绍特殊情况)不会立即更新state的值;
  2. setState通过引发一次组件的更新过程来引发重新绘制;
  3. 多次setState函数调用产生的效果会合并。

对于第一点,引用网上的例子:

function incrementMultiple() {
  this.setState({count: this.state.count + 1});
  this.setState({count: this.state.count + 1});
  this.setState({count: this.state.count + 1});
}

上面的函数运行时,似乎对state.count的值加了3次,但实际上只加了一次,原因正是setState不会立即改变state的值所以后面两次的this.state其实还是最初的state。

第二点需要提到上面的组件更新期的声明周期,setState调用引起的React的更新生命周期函数4个函数:

  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()

当shouldComponentUpdate函数被调用的时候,this.state没有得到更新。
当componentWillUpdate函数被调用的时候,this.state依然没有得到更新。

直到render函数被调用的时候,this.state才得到更新。

(或者,当shouldComponentUpdate函数返回false,这时候更新过程就被中断了,render函数也不会被调用了,这时候React不会放弃掉对this.state的更新的,所以虽然不调用render,依然会更新this.state。)
所以setState一般不会立即更新state的值,知道render()函数触发。

对于第三点可以简单理解为:
连续调用了两次this.setState,但是只会引发一次更新生命周期,不是两次,因为React会将多个this.setState产生的修改放在一个队列里,缓一缓,攒在一起,觉得差不多了再引发一次更新过程。这样做的好处是,不用每次setState就去触发一次render(),这样太消耗性能。

另外setState()可以接受一个函数作为参数,也就是说可以在里面参入回调函数:

function increment(state, props) {
  return {count: state.count + 1};
}

function incrementMultiple() {
  this.setState(increment);
  this.setState(increment);
  this.setState(increment);
}

值得注意的是:同样是把状态中的count加1,但是函数increment的状态的来源不是this.state,而是输入参数state,所以加1是累加上去的。
值得一提的是,在increment函数被调用时,this.state并没有被改变,依然,要等到render函数被重新执行时(或者shouldComponentUpdate函数返回false之后)才被改变。这也就是说如果, this.setState(increment)中插入 this.setState({count: this.state.count + 1})会让前面的努力白费。如下:

 function incrementMultiple() {
  this.setState(increment);
  this.setState(increment);
  this.setState({count: this.state.count + 1});
  this.setState(increment);
}

在几个函数式setState调用中插入一个传统式setState调用(嗯,我们姑且这么称呼以前的setState使用方式),最后得到的结果是让this.state.count增加了2,而不是增加4,所以不宜混用两种发法。

更详细请点击原文参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容