按照官方文档
目前react的mount阶段,将按以下顺序调用这些方法:
该方法只要父组件调用了
render
方法就会调用(会判断oldProps !== newProps
),换句话来说,对于父组件没有render
,子组件的该生命周期就不会调用。
遗留方法
*UNSAFE_componentWillMount()
取消UNSAFE_componentWillMount()
的原因:
- 数据初始化(应该放在
constructor
) -
fetch
数据- 并没有可以获得优先渲染优势,因为
reconciliation
和commit
是同步操作 - 服务端渲染会有问题,异步模式下会触发多次fetch数据
- 应该放在companyDidMount生命周期内
- 并没有可以获得优先渲染优势,因为
- 订阅事件造成内存泄漏
- 服务端渲染
componentWillUnmount
不会调用,异步会被打断,导致componentWillUnmount
不会调用
- 服务端渲染
getSnapshotBeforeUpdate(props, state)
不传递preProps原因:
- 第一次渲染的过程,
preProps
可能为null
, 所以要对preProps
做if-not-null
判断 - 不需要保存
preProps
为react
未来版本降低内存做好准备
update阶段,将按以下顺序调用这些方法:
static getDerivedStateFromProps(props, state)
shouldComponentUpdate(nextProps, nextState)
render()
getSnapshotBeforeUpdate(props, state)
componentDidUpdate(preProps, preState, snapshot)
遗留方法
*UNSAFE_componentWillUpdate(nextProps, nextState)
*UNSAFE_componentWillReceiveProps(preProps, preState)
取消UNSAFE_componentWillReceiveProps(preProps, preState) ,UNSAFE_componentWillUpdate(nextProps, nextState)
原因:
- 这两个生命周期都在
reconciliation
过程中 - 在异步模式下,
reconciliation
会被打断,所以可能触发多次 - 如果在这两个生命周期做一些
fetch
请求、props
的回调等产生副作用的事情,那么可能会导致执行多次
卸载阶段,将调用下面生命周期:
Derive state 生命周期会有固有的问题:
(UNSAFE_componentWillReceiveProps(preProps, preState),static getDerivedStateFromProps(props, state)
)
- 组件有受控状态和非受控状态,
Derive state
生命周期通常指受控状态(即state
由props
决定),但是如果组件又可以自行设置state,那么state的来源就有props
和组件自身行为,这违反了数据单一来源的原则
在Derive state
生命周期中没有条件的直接接受父组件的props
危害如下:
- 如果子组件是一个
input
元素,自身输入会改变state
的值,也接受父组件的props
来修改state
,如果组件通过输入有了新的state
,副组件的props
保存的是旧的数据,一旦父组件setState
,那么子组件刚才的输入的state的值就会被父组件的旧的数据覆盖从而丢失了数据- 可以通过对比
nextProps
和this.props
来避免这个问题,但是又会引入新的问题,特别是当组件被复用的时候,对比的结果会导致组件无法更新
解决办法:
- 将组件完全改造成受控组件,最优
- 将组件完全改造成非受控组件,但是有无法
reset
组件的问题:
- 用
key
的办法来从新reset
组件;假如不想重新渲染组件,也可以使用的key
作为一个props
的属性来使用Derive state
生命周期进行reset
过程,- 采用
ref
的方法直接调实例方法
- 对于这种
state
随着props
变化的情况可以使用memoization
方案
网友评论