按照官方文档
目前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方案