为什么React16弃用了componentWillMount、componentWillReceiveProps,componentWillUpdate
为什么不推荐在 componentWillMount 里最获取数据的操作
要深入回答这些问题, 就不得不提到一个React 的核心概念: React Fiber.
React Fiber 是在 v16 的时候引入的一个全新架构, 旨在解决异步渲染问题。
新的架构使得使得 React 用异步渲染成为可能,但要注意,这个改变只是让异步渲染成为可能。
但是React 却并没有在 v16 发布的时候立刻开启,也就是说,React 在 v16 发布之后依然使用的是同步渲染。
不过,虽然异步渲染没有立刻采用,Fiber 架构还是打开了通向新世界的大门,React v16 一系列新功能几乎都是基于 Fiber 架构。
说到这, 也要说一下 同步渲染 和 异步渲染.
我们都知道React 是facebook 推出的, 他们内部也在大量使用这个框架, 然后就发现了很多问题, 比较突出的就是渲染问题。
他们的应用是比较复杂的, 组件树也是非常庞大, 假设有一千个组件要渲染, 每个耗费1ms, 一千个就是1000ms, 由于javascript 是单线程的, 这 1000ms 里 CPU 都在努力的干活, 一旦开始,中间就不会停。 如果这时候用户去操作, 比如输入, 点击按钮, 此时页面是没有响应的。 等更新完了, 你之前的那些输入就会啪啪啪一下子出来了。
这就是我们说的页面卡顿, 用起来很不爽, 体验不好。
这个问题和设备性能没有多大关系, 归根结底还是同步渲染机制的问题。
React 版本(v16.7), 当组件树很大的时候,也会出现这个问题, 逐层渲染, 逐渐深入,不更新完就不会停。
函数调用栈如图所示:

Fiber 的做法是:分片。
把一个很耗时的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。 而维护每一个分片的数据结构, 就是Fiber。
用一张图来展示Fiber 的碎片化更新过程:

中间每一个波谷代表深入某个分片的执行过程,每个波峰就是一个分片执行结束交还控制权的时机。
在React Fiber中,一次更新过程会分成多个分片完成,所以完全有可能一个更新任务还没有完成,就被另一个更高优先级的更新过程打断,这时候,优先级高的更新任务会优先处理完,而低优先级更新任务所做的工作则会完全作废,然后等待机会重头再来。
因为一个更新过程可能被打断,所以React Fiber一个更新过程被分为两个阶段: render phase & commit phase.
有了Fiber 之后, react 的渲染过程不再是一旦开始就不能终止的模式了, 而是划分成为了两个过程: 第一阶段和第二阶段, 也就是官网所谓的 render phase & commit phase。
在 Render phase 中, React Fiber会找出需要更新哪些DOM,这个阶段是可以被打断的, 而到了第二阶段commit phase, 就一鼓作气把DOM更新完,绝不会被打断。
这两个阶段, 分界点是什么呢?
其实是 render 函数。 而且, render 函数 也是属于 第一阶段 render phase 的。
那这两个 phase 包含的的生命周期函数有哪些呢?
render phase:
commit phase:

因为第一阶段的过程会被打断而且“重头再来”,就会造成意想不到的情况。
比如说,一个低优先级的任务A正在执行,已经调用了某个组件的componentWillUpdate函数,接下来发现自己的时间分片已经用完了,于是冒出水面,看看有没有紧急任务,哎呀,真的有一个紧急任务B,接下来React Fiber就会去执行这个紧急任务B,任务A虽然进行了一半,但是没办法,只能完全放弃,等到任务B全搞定之后,任务A重头来一遍,注意,是重头来一遍,不是从刚才中段的部分开始,也就是说,componentWillUpdate函数会被再调用一次。
在现有的React中,每个生命周期函数在一个加载或者更新过程中绝对只会被调用一次;在React Fiber中,不再是这样了,第一阶段中的生命周期函数在一次加载和更新过程中可能会被多次调用!