blog
blog copied to clipboard
Lifecycle after React 16.3
React 16.3 是比较重大的一次版本更新,涉及 新的lifecycle methods
,全新的Context Api
,Ref Api
等
首先吸引到我的当然是生命周期的改变,就来简单谈一下,后面会写详细的帖子关于修改生命周期的原因
The New Lifecycle
涉及改变的三个 Lifecycle func:
-
componentWillMount
-
componentWillUpdate
-
componentWillReceiveProps
在17.0版本之前,16.3版本开始,这三个 methods 将带有 UNSAFE_ 的前綴来标识,目的当然是为了让我们逐步的去修改项目中有关于这些Lifecycle func的代码,那 React 为了让我们更好的完成升级,也列出了建议:
componentWillMount
更换声明周期:
componentWillMount
——> componentDidMount
这里有一个小问题,componentWillMount
似乎是请求数据方法的理想位置,所以有时候我们会将 请求后端的callback 写在其中,以求更早的请求数据(虽然我还没这么写过),但其实这样是误用
在组件的首次render之前会调用这个方法,所以在这个方法中 setState 不会发生重新渲染(re-render);
而且由于这是 Server side render 唯一的Lifecycle func,所以如果项目是基于SSR的,那 componentWillMount 很可能被调用很多次
BTW,在ES6的Class中,constructor() 可以作为 componentWillMount 的替代
componentWillUpdate
更换声明周期:
componentWillUpdate
——> componentDidUpdate
这个很简单就不说啦
componentWillReceiveProps
这个可能是修改起来比较麻烦的一个了,使用的机会比较多,一般用作:
- 根据 Props来修改 State
- Props 改变时去调用一些Func,或者做出一些不会修改state的操作
针对第一种,更换方法:
componentWillReceiveProps
——> getDerivedStateFromProp
16.3 提出了一个新的静态方法:getDerivedStateFromProp Method Signature:
static getDerivedStateFromProps(nextProps, prevState) {
// ...
}
注意这是一个静态方法,也就是说,在内部使用 this
是指向类的,而不是实例,所以无法使用 this.setState,那么如何更新状态呢?
其实只需要返回更新的状态就可以了,或是 null :表示state不需要更新
官方示例:
// before
componentWillReceiveProps(nextProps) {
if (this.props.currentRow !== nextProps.currentRow) {
this.setState({
isScrollingDown: nextProps.currentRow > this.props.currentRow
})
}
}
// after
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.currentRow !== prevState.lastRow) {
return {
isScrollingDown: nextProps.currentRow > prevState.lastRow,
lastRow: nextProps.currentRow
}
}
// Return null to indicate no change to state.
return null
}
通过例子可以得知,以往依赖比较 this.props.xxx
与 nextProps.xxx
是不行了。在 getDerivedStateFromProps
中,需要将要比较的值也存到state当中,才能在之后通过 nextProps.xxx vs prevState.xxx
做比較
返回值的机制和使用 setState 的机制是类似的 —— 只需要返回发生改变的那部分状态,其他的值会保留。
针对第二种,使用 compomentDidUpdate
:
基本上在不更新state的情况下,使用这个methods来代替是完全可行的,因为包括了我们需要用的到prevProps,并且 componentDidUpdate 内部可以访问this.props,利用这两个我们可以作出各种比较
componentDidUpdate(prevProps, prevState) {
if (this.props.reqPending !== prevProps.reqPending && !this.props.reqPending) {
if(!this.props.error){
this.props.history.push('/next-page')
}
}
}
总结
这张 React 16.3 生命周期来自于 Dan神 的twitter
详细介绍了 lifecycle methods 的执行顺序。
其实目前的16.4作出了一些小修改:
日后会写关于这个的帖子。
有个开发者将生命周期图做成动态的demo了,方便查询不同版本的差异 :链接