React 16生命周期整理
新项目用的React16.6, 遂整理一下新版本带来的生命周期改变。
最大的改动是生命周期去掉了三个
componentWillMount
componentWillReceiveProps
componentWillUpdate
并且加了两个静态方法
static getDerivedStateFromProps
getSnapshotBeforeUpdate
刚开始用的时候非常不习惯,不是很能理解为什么16里面React要把这三个生命周期方法干掉。专程google了一下:
React打算推出新的Async Rendering,提出一种可被打断的生命周期,而可以被打断的阶段正是实际dom挂载之前的虚拟dom构建阶段,也就是要被去掉的三个生命周期。生命周期一旦被打断,下次恢复的时候又会再跑一次之前的生命周期,因此componentWillMount, componentWillReceiveProps, componentWillUpdate都不能保证只在挂载/拿到props/状态变化的时候刷新一次了,所以这三个方法被标记为不安全。而在整个16版本里都能无障碍的使用旧的这三个生命周期,但值得注意的是,旧的生命周期(unsafe)不能和新的生命周期同时出现在一个组件,否则会报错“你使用了一个不安全的生命周期”。(引用自https://juejin.im/post/5aca20c96fb9a028d700e1ce)


我们可以看见除了shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。我们在render之前的操作被限制在只能根据props和state的变化生成新的state。
getDerivedStateFromProps:
之前没怎么关注这个文档,根据自己项目实践中发现getDerivedStateFromProps无论是Mounting还是Updating都会被调用(在render之前)。返回一个新对象来更新当前的state或者返回null不改变state。
getSnapshotBeforeUpdate:
这个方法暂时还没有实践过,从查到的文档来看被调用于render之后。它使组件可以在可能更改之前从DOM捕获一些信息(例如滚动位置)。此生命周期返回的任何值都将作为参数传递给componentDidUpdate。
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('enter getSnapshotBeforeUpdate.....');
return 'I will see you in componentDidUpdate';
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('enter componentDidUpdate snapshot: ', snapshot);
// you will see 'I will see you in componentDidUpdate' in consolelog
}
componentDidCatch: 错误handler
componentDidCatch(err, info)
React16提供了错误处理的生命周期方法,在任何子组件渲染期间,生命周期方法中或者构造函数 constructor 发生错误时调用。但通过文档来看componentDidCatch不会捕获下面的错误:
- 事件处理 (Event handlers) (因为事件处理不发生在 React 渲染时,报错不影响渲染)
- 异步代码 (Asynchronous code) (e.g. setTimeout or requestAnimationFrame callbacks)
- 服务端渲染 (SSR)
- 错误边界本身(而不是子组件)抛出的错误
参考鸣谢
https://www.jianshu.com/p/514fe21b9914
https://juejin.im/post/5aca20c96fb9a028d700e1ce