react学习笔记(12) - 生命周期中使用setState以及生命周期中的性能优化
React
学习笔记 - 生命周期中使用setState
以及生命周期中的性能优化
1. 生命周期中使用setState
- 一般来讲是不推荐在生命周期钩子中使用
setState
,因为每一次使用setState
就意味着数据更新,页面的重新渲染,页面重新渲染就会使得某些生命周期重新执行一遍,也就是说,在某些生命周期钩子(componentWillUpdate
,shouldComponentUpdate
)中使用setState
会使组件陷入死循环,而新的生命周期钩子中(getSnapshotBeforeUpdate
,以及getDerivedStateFromProps
)则无法使用setState
,因为这两个钩子都需要静态引用(加上前缀static
),也就是说这两个钩子没有this
指向,但是他们提供了一些形参来让你获取最新的state
或者props
数据
因此要想了解在生命周期中如何使用
setState
,就需要下面的分析了!
一. 首先我们需要了解一下React
生命周期的成员以及它们的执行流程:
React
生命周期可以分为两条执行流程:
初始化:初始进入页面 →
constructor
→componentWillMount
(getDerivedStateFromProps
[新]) → render →componentDidMount
→componentWillUnmount
;数据更新:
setState
→componentWillReceiveProps
(getDerivedStateFromProps
[新]) →shouldComponentUpdate
→componentWillUpdate
[旧,后续可能会被取消] →render
→getSnapshotBeforeUpdate[新,取代componentWillUpdate]
→componentDidUpdate
→componentWillUnmount
。
- 更新流程需要提到两点:一点是
componentWillReceiveProps
中使用setState
,state
会被收集储存起来,这里是区别于上面componentWillMount
中state
合并到初始数据中的。这里提一下:shouldComponentUpdate
如果return
=>false
,则不会执行更新(render
)。
1. 初始化
1、首先,进入页面,会初始化页面数据(
state
,props
,context
等…),等待备用;2、然后,设置 生命状态 为:
MOUNTING
,这个状态下面会说明它的用途,这里我们先按照流程继续往下走;3、接下来,在
componentWillMount
中,setState
操作,只是把state
合并到初始化状态中,而根本不会触发render
;在这里更新state
,就等同于直接写在this.state
中,所以,在此生命周期中的setState
根本没有意义;4、执行到这里,生命状态 会被重置为
null
,之后是渲染页面(即执行render
);5、最后,渲染完以后,执行
componentDidMount
,这里使用setState
即会正常触发重新渲染了,更新state
。(接下来,就是更新流程了!!)
2. 数据更新
1、首先,
react
会比较前后元素、状态等是否不同,如果不同则正式发起更新;2、然后,生命状态 被设置为
RECEIVE_PROPS
(注意:此时生命周期中,setState
不会触发更新,而是会做其他处理);3、接下来,
componentWillReceiveProps
中的setState
就不会执行更新,而是合并挂载起来,等待render
时统一更新;4、到这里,生命状态 会重置为null;然后
shouldComponentUpdate
中会判断是否更新;之后是componentWillUpdate
。
注意:
shouldComponentUpdate
和componentWillUpdate
执行的时候,生命状态 已经被重置为null
,在它们里面的setState
会触发更新,那么在其间使用呢?会造成什么?答案就是:在一个更新周期还没有render
之前,再次发起updateComponent
,直接导致递归更, 也就是死循环,由此可见,在这两个生命周期钩子中是禁止使用setState
的
5、最后,渲染页面;再执行
componentDidUpdate
;它里面执行setState
,会触发更新,不同的是render
完成之后再发起的reRender
。虽然这儿区别于上面两个生命周期中使用的情况,但是会一遍一遍的更新,这肯定也是不合理的,所以需要有条件的使用setState
。
总结:
生命周期中setState
的使用情况:
- 无意义使用:
componentWillMount
,componentWillUnmount
; - 有条件使用:
componentDidUpdate
; - 禁止使用:
componentWillUpdate
,shouldComponentUpdate
; - 正常使用:
componentWIllReceiveProps
,componentDidMount
。
生命周期中setState
是否触发更新:
componentWillMount
和componentWillReceiveProps
中,setState
会被react
内部处理,而不触发render
;其他生命周期均正常出发更新渲染。
生命周期中的性能优化
- 一般看来讲,生命周期中的性能优化一般有两种方法:第一种是手动优化,就是之前博客提到的生命周期钩子中,
shouldComponentUpdate
的使用,通过我们手动对比判断通信传递中的状态数据
是否前后一致,一致则组件不需要重新渲染一边
// 更新时:生命周期1: shouldComponentUpdate(nextProps, nextState):用于性能优化 |
- 第二种就是
React
中内置的智能对比传输前后数据状态
,PureComponent
,它会自动的帮你 比较新props
跟 旧的props
, 新的state
和老的state
(值相等,或者对象含有相同的属性、且属性值相等 ),决定shouldcomponentUpdate
返回true
或者false
, 从而决定要不要呼叫render function
。但是要注意如果你的你的state
或props
『永远都会变
』,那PureComponent
并不会比较快,因为shallowEqual
也需要花时间。
// 使用方法,在引入React组件时直接引入PureComponent取代Component即可 |