# React生命周期分析

参考文章:原文链接

参考文章:ReactV16.3即将更改的生命周期

在V16版本中引入了Fiber机制。这个机制在一定程度上影响了部分生命周期的调用,并且引入了新的2个API来解决问题。

在之前的版本中,如果你拥有一个很复杂的复合组件,然后改动了最上层组件的state,那么调用栈可能会很长 image 调用栈过长,再加上中间进行了复杂的操作,就可能导致长时间阻塞主线程,带来不好的用户体验。Fiber就是为了解决该问题而生。

Fiber本质上是一个虚拟的堆栈帧,新的调度器会按照优先级自由调度这些帧,从而将之前的额同步渲染改成异步渲染,在不影响体验的情况下去分段计算更新。 image 对于如何区别优先级,React有自己的一套逻辑。对于动画这种实时性很高的东西,也就是16ms必须渲染一次保证不卡顿的情况下,Reac会每16ms(以内)暂停一下更新,返回来继续渲染动画。

对于异步渲染,现在渲染有两个阶段:reconciliationcommit。前者过程是可以打断的,后者不能暂停,会一直更新界面直到完成。

# Reconciliation阶段

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

# Commit阶段

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

因为reconciliation阶段是可以被打断的,所以reconciliation阶段会执行的生命周期函数就可能会出现调用多次的情况,从而引起Bug。所以对于reconciliation阶段调用的几个函数,除了shouldComponentUpdate以外,其他都应该避免去使用,并且V16也引入了新的API来解决这个问题。

getDerivedStateFromProps用于替换componentWillReceiveProps,该函数会在初始化和update时被调用

class ExampleComponent extends React.Component {
  state = {}
  static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.someMirroredValue !== nextProps.someValue) {
      return {
        derivedData: computeDerivedState(nextProps),
        someMirroredValue: nextProps.someValue
      };
    }

    // Return null to indicate no change to state.
    return null;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

getSnapshotBeforeUpdate用于代替componentWillUpdate,该函数会在update后的DOM更新前被调用,用于读取最新的DOM数据

# V16 生命周期函数用法建议

class ExampleComponent extends React.Component {
  // 用于初始化 state
  constructor() {}
  // 用于替换 `componentWillReceiveProps` ,该函数会在初始化和 `update` 时被调用
  // 因为该函数是静态函数,所以取不到 `this`
  // 如果需要对比 `prevProps` 需要单独在 `state` 中维护
  static getDerivedStateFromProps(nextProps, prevState) {}
  // 判断是否需要更新组件,多用于组件性能优化
  shouldComponentUpdate(nextProps, nextState) {}
  // 组件挂载后调用
  // 可以在该函数中进行请求或者订阅
  componentDidMount() {}
  // 用于获得最新的 DOM 数据
  getSnapshotBeforeUpdate() {}
  // 组件即将销毁
  // 可以在此处移除订阅,定时器等等
  componentWillUnmount() {}
  // 组件销毁后调用
  componentDidUnMount() {}
  // 组件更新后调用
  componentDidUpdate() {}
  // 渲染组件函数
  render() {}
  // 以下函数不建议使用
  UNSAFE_componentWillMount() {}
  UNSAFE_componentWillUpdate(nextProps, nextState) {}
  UNSAFE_componentWillReceiveProps(nextProps) {}
}
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

# 新增的生命周期

新增的getDerivedStateFromPropsgetSnapshotBeforeUpdate如果存在以前的willMount,willReceiveProps,willUpdate,会报警告

#

getDerivedStateFromProps

  1. 该方法是静态的,使用需要加上static
  2. 该方法返回值将会更新state(返回null不更新),这样我们可以将props的值返回更新state,那么所有状态都由state来维护

# getSnapshotBeforeUpdate

  1. 和以前的区别在于返回值将作为didUpdate的第三个参数