前言
- 最近在工作上遇到一些奇怪的bug,具体表现在componentWillReceiveProps这一生命周期钩子函数在一些特殊情况下会重复执行两次,从而导致我们的一些报错信息提示弹了两次,影响到了用户体验,同时也会影响到页面的流畅性和性能。
- 对这种情况的解决方式是使用componentDidUpdate这一生命周期函数替换componentWillReceiveProps。这个方法也是React官方文档所推荐的,当然解决了这一个问题后,我自然也是得搞清楚其背后的原理,因此在此作一笔记记录学习过程。
- 参考资料:
正文
- 首先,从v16.3.0起,React便已经将如下三个钩子函数标为UNSAFE的,并且是不推荐使用
- componentWillMount
- componentWillRecieveProps
- componentWillUpdate
- 原因有二:
- react推出了新的生命周期钩子来替换这三个。
- 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没有变化,只是父组件更新也会调用该钩子函数,具体到项目上就是会出现一些莫名其妙的重复调用