Fiber版本生命周期浅析

React 16.4版本生命周期变化

16版本之前的componentWillMount、componentWillReceiveProps、componentWillUpdate将被移除;
新增 getDerivedStateFromProps、getSnapshotBeforeUpdate ;
react框架将采用异步渲染机制,上述三个周期函数将会变的不安全,产生bug;
另新增 componentDidCatch 周期函数,处理render函数渲染错误的捕捉;

componentWillMount周期函数

  • 若将异步请求数据的业务放在这个函数内,也会导致首屏白屏,怎么滴也赶不上render函数渲染
  • 若是服务端渲染,此函数将会被执行两次
  • 服务端渲染也不能保证componentWillUnmount周期函数执行,若在componentWillMount订阅事件,则会造成内存泄漏
  • 尽量将数据请求放在componentDidMount函数内执行,此时dom已挂载完毕,不会造成影响,比较安全;

componentWillReceiveProps 和 getDerivedStateFromProps 的比较

应用场景: 当组件内的state和props紧密联系时

  • componentWillReceiveProps(nextProps) 更新state 执行回调函数
  • getDerivedStateFromProps(nextProps, prevState) 只专注于props和state的比较,来更新state
  • 比较新旧的代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // before
    componentWillReceiveProps(nextProps) {
    if (nextProps.isLogin !== this.props.isLogin) {
    this.setState({
    isLogin: nextProps.isLogin,
    });
    }
    if (nextProps.isLogin) {
    this.handleClose();
    }
    }
    // after
    static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.isLogin !== prevState.isLogin) {
    return {
    isLogin: nextProps.isLogin,
    };
    }
    return null;
    }

    componentDidUpdate(prevProps, prevState) {
    if (!prevState.isLogin && this.props.isLogin) {
    this.handleClose();
    }
    }

在新版本中,官方将更新 state 与触发回调重新分配到了 getDerivedStateFromProps 与 componentDidUpdate 中,使得组件整体的更新逻辑更为清晰。而且在 getDerivedStateFromProps 中还禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去做其他一些让组件自身状态变得更加不可预测的事情。

componentWillUpdate 和 getSnapshotBeforeUpdate

  • componentWillUpdate 都有可能在一次更新中被调用多次,显然是不可取的,将回调函数放在componentDidUpdate
  • componentWillUpdate
  • getSnapshotBeforeUpdate(prevProps, prevState) 返回值作为第三个参数传入componentDidUpdate
    官方例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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;
    };
    }
-------------本文结束感谢您的阅读-------------