React的componentWillXXX

2022-7-13 14:34:34

#react

96

前言

  • 最近在工作上遇到一些奇怪的bug,具体表现在componentWillReceiveProps这一生命周期钩子函数在一些特殊情况下会重复执行两次,从而导致我们的一些报错信息提示弹了两次,影响到了用户体验,同时也会影响到页面的流畅性和性能。
  • 对这种情况的解决方式是使用componentDidUpdate这一生命周期函数替换componentWillReceiveProps。这个方法也是React官方文档所推荐的,当然解决了这一个问题后,我自然也是得搞清楚其背后的原理,因此在此作一笔记记录学习过程。
  • 参考资料:

正文

  • 首先,从v16.3.0起,React便已经将如下三个钩子函数标为UNSAFE的,并且是不推荐使用
    • componentWillMount
    • componentWillRecieveProps
    • componentWillUpdate
  • 原因有二:
    1. react推出了新的生命周期钩子来替换这三个。
    2. react从legacy模式迁移到Concurrent模式后,这三个钩子的表现会变得不一致。

错误调用的生命周期钩子

  if (
    !hasNewLifecycles &&
    (typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
      typeof instance.componentWillReceiveProps === 'function')
  ) {
    if (oldProps !== newProps || oldContext !== nextContext) {
      //  调用componentWillRecieveProps
      callComponentWillReceiveProps(
        workInProgress,
        instance,
        newProps,
        nextContext,
      );
    }
  }

React源码

  • 从这段代码中可以看出,当oldPros和newProps不全等或者是oldContext和nextContext不全等时,便会调用componentWillRecieveProps
  • 但是,oldProps来自组件上次更新时的props,而newProps来自于ClassComponent调用this.render返回JSX中的props参数
  • 因此这两个参数的引用是不一致的,所以在全等比较时总为false。这就导致了每次父组件更新都会触发当前组件的componentWillRecieveProps这个生命钩子
  • 这就意味着就算props没有变化,只是父组件更新也会调用该钩子函数,具体到项目上就是会出现一些莫名其妙的重复调用