React v16.4 的生命周期

依然是先看图:

life

变更缘由

原来( React v16.0 前)的生命周期在 React v16.0 推出的 Fiber 之后就不合适了,因为如果要开启 async rendering, 在 render 函数之前的所有函数,都有可能被执行多次。
有上一篇我们知道下面的这些生命周期都是原来( React v16.0 前)在 render 前执行的:

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

除了 shouldComponentUpdate ,其他在 render 函数之前的 所有函数( componentWillMountcomponentWillReceivePropscomponentWillUpdate)都被 getDerivedStateFromProps 替代。
也就是用一个静态函数 getDerivedStateFromProps 来取代被 deprecate 的几个生命周期函数,就是强制开发者在 render 之前只做无副作用的操作,而且能做的操作局限在根据 propsstate 决定新的 state
React v16.0 刚推出的时候,是增加了一个 componentDidCatch 生命周期函数,这只是一个增量式修改,完全不影响原有生命周期函数;但是,到了 React v16.3 ,大改动来了,引入了两个新的生命周期函数。

新引入了两个新的生命周期函数: getDerivedStateFromProps,getSnapshotBeforeUpdate

  1. getDerivedStateFromProps
    getDerivedStateFromProps 本来( React v16.3 中)是只在创建和更新(由父组件引发部分),也就是不是不由父组件引发,那么 getDerivedStateFromProps 也不会被调用,如自身 setState 引发或者 forceUpdate 引发。

life

这样的话理解起来有点乱,在 React v16.4 中改正了这一点,让 getDerivedStateFromProps 无论是 Mounting 还是 Updating,也无论是因为什么引起的 Updating ,全部都会被调用,具体可看 React v16.4 的生命周期图。
React v16.4 后, getDerivedStateFromProps(props, state) 在组件创建时和更新时的 render 方法之前调用,它应该返回一个对象来更新状态,或者返回 null 来不更新任何内容。

  1. getSnapshotBeforeUpdate
    getSnapshotBeforeUpdate() 被调用于 render 之后,可以读取但无法使用 DOM 的时候。它使您的组件可以在可 能更改之前从 DOM 捕获一些信息(例如滚动位置)。此生命周期返回的任何值都将作为参数传递给 componentDidUpdate()

官网给的例子:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }
getSnapshotBeforeUpdate(prevProps, prevState) { //我们是否要添加新的 items 到列表?
// 捕捉滚动位置,以便我们可以稍后调整滚动.
if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) { //如果我们有snapshot值, 我们已经添加了 新的items.
// 调整滚动以至于这些新的items 不会将旧items推出视图。
// (这边的snapshot是 getSnapshotBeforeUpdate方法的返回值) if (snapshot !== null) {
    const list = this.listRef.current;
    list.scrollTop = list.scrollHeight - snapshot;
  }
}
render() {
  return (
    <div ref={this.listRef}>{/* ...contents... */}</div>
  );
}
posted @ 2019-12-01 01:11  木子蔻  阅读(467)  评论(0编辑  收藏  举报