关于react的新生命周期

2019-04-20  本文已影响0人  王小滚

在react中旧的生命周期其实已经十分完整,基本可以捕捉到组件更新的每一个state/props/ref,没有什从逻辑上的毛病。

1. 旧的生命周期
旧的生命周期

当然我们现在,在整个16版本里都能无障碍的使用旧的三生命周期,但旧的生命周期(unsafe)不能和新的生命周期同时出现在一个组件,否则会报错。

可以看出三个即将被删除的生命周期,都是在实际dom挂载之前的虚拟dom构建阶段。这也正是react打算在17版本推出新的Async Rendering,提出一种可被打断的生命周期,而可以被打断的正是即将要被去掉的三个生命周期。生命周期一旦被打断,下次恢复的时候又会再跑一次之前的生命周期了。

2. 新的生命周期

接下来我们看下新增的生命周期:

  1. static getDerivedStateFromProps

乍看下来 static getDerivedStateFromProps和即将被删掉componentWillReceiveProps这二者好像并没有什么本质上的区别,但这却是这其实是最能够体现 React 团队对于软件工程深刻理解的一个改动,即 React 团队试图通过框架级别的 API 来约束或者说帮助开发者写出可维护性更佳的 JavaScript 代码。

class test extends Component {
    // before
  componentWillReceiveProps(nextProps) {
    if (nextProps.isSupportCaps !== this.props.isSupportCaps) {
      this.setState({   
        isSupportCaps: nextProps.isSupportCaps, 
      });
    }
    if (nextProps.isSupportCaps) {
      this.handleCaps();
    }
  }

  // after
  static getDerivedStateFromProps (nextProps, prevState) {
    if (nextProps.isSupportCaps !== prevState.isSupportCaps) {
      return {
        isSupportCaps: nextProps.isSupportCaps,
      };
    }
    return null;
  }
  componentDidUpdate(prevProps, prevState) {
    if (!prevState.isSupportCaps && this.props.isSupportCaps) {
      this.handleCaps();
    }
  }
}

在新版本中,官方将更新 state 与触发回调重新分配到了 getDerivedStateFromPropscomponentDidUpdate 中,使得组件整体的更新逻辑更为清晰。

  1. getSnapshotBeforeUpdate
class ScrollingList extends React.Component {
  listRef = null;

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      return (
        this.listRef.scrollHeight - this.listRef.scrollTop
      );
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      this.listRef.scrollTop =
        this.listRef.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.setListRef}>
        {/* ...contents... */}
      </div>
    );
  }

  setListRef = ref => {
    this.listRef = ref;
  };
}

getSnapshotBeforeUpdate 的使用场景一般是获取组建更新之前的滚动条位置。

上一篇 下一篇

猜你喜欢

热点阅读