React 生命周期“废旧立新”背后的思考
前言
当我们学习React的时候,总少不了对React生命周期的讨论。在React16.x这个版本,React官方对React生命周期作出一系列调整,我们会思考,为什么会作出这样的调整呢?今天就让我们来探讨一下,React 生命周期“废旧立新”的原因。
1.老新生命周期对比
1.1 老生命周期
1. 初始化阶段
2. 运行中阶段
3. 销毁阶段
1.2 新生命周期
(1)getDerivedStateFromProps 第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) ,返回一个对象作为新的state,返回null则说明不需要在这里更新state。
(2) getSnapshotBeforeUpdate 取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。
2. 老生命周期的问题
首先必须承认,老生命周期是的存在一系列问题的。
- componentWillMount ,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃
- componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
- componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致 状态不可信
因为这些问题,React官方在16.x版本放弃了componentWillMount、componentWillReceiveProps、componetWillupdate这三个钩子,增加了getDerivedStateFromProps、getSnapshotBeforeUpdate这两个钩子
3. 透过现象看本质:React16为何作出如此改变?
先来引出两个观点:
1.Fiber是React16对React核心算法的一次重写
2.Fiber会使原本同步的渲染过程变成异步
换个角度看生命周期工作流
Fiber架构的重要特征就是可以被打断的异步渲染模式,根据“能否被打断”这一标准,React 16的生命周期被划分为了render和commit两个阶段
render阶段在执行过程中允许被打断,而commit阶段则总是同步进行的
React 生命周期“废旧立新”背后的思考
-
render阶段是允许暂停、终止和重启的,这就导致render阶段的生命周期都是有可能被重复执行。componentWillMount、componentWillReceiveProps、componetWillupdate都处于render阶段,都有可能重复被执行。包括setState、fetch发起异步请求、操作真实DOM等等。因此render阶段需要废弃componentWillMount、componentWillReceiveProps、componetWillupdate这些钩子,从而将setState、fetch发起异步请求、操作真实DOM等等转移到其他生命周期里去做。
-
在Fiber带来的异步渲染机制下,可能会导致非常严重的Bug。由于render阶段里的生命周期都可以重复执行,在componentWillxxx被打断+重启多次后,就会发出多个付款请求。
-
即使你没有开启异步,React 15下也有不少人能把自己“玩死”。React 16改造生命周期的主要动机,是为了配合Fiber架构带来的异步渲染机制,针对生命周期中长期被滥用的部分推行了具有强制性的最佳实践,确保了Fiber机制下数据和视图的安全性,同时也确保了生命周期方法的行为更加纯粹、可控、可预测。
结尾
看到这里,文章就已经结束了。相信这篇文章能够让你对React生命周期有了一定的了解,同时也能对React 生命周期“废旧立新”背后有了一定的了解,希望这篇文章能在学习、工作或者面试带给你一点点帮助。后续也会出更多关于前端的、有意思的内容,大家可以期待一下~
转载自:https://juejin.cn/post/7151966996819607588