前言
今天这篇日记主要是探究一下16,17,18这三个版本的渲染及useEffect的顺序问题。
我相信大家对这个丝毫不陌生,但你是否能够在不进行实践输出的情况下明确知道输出顺序吗?如果你还有疑问或者迟疑,那么请耐心看下去。
另外其他的小伙伴或许也有类似的文章,那么可以互相印证了解学习,如果众说纷纭,那么不妨亲自上手试试。
实践
下面的实践内容,为了更直观,所以贴了很多图片,排版不是很好,希望大家多多包涵,后期有时间了还会继续改进优化。
v16.8.0
package.json
index.js 入口页
App.tsx
left.tsx 子组件
center.tsx 兄弟组件
输出结果
从上面的运行结果来看,函数组件内部都是运行两次渲染,只有useEffect运行一次。
1. 渲染顺序(mount):```父组件 =》子组件```
2. 执行顺序(useEffect):```子组件 =》父组件```
3. 整体顺序(mount =》 useEffect):```父组件 =》子组件 =》兄弟组件 =》父组件```
v17.0.0
除了 react 和 react-dom 版本号不一样之外,其他全部一样,就不再贴app, left, center这些组件信息的图片。
大家发现没有,17.0.0版本的运行和16.8.0的不一样了,渲染和useEffect在各自的组件内仅仅是执行一次。
17版本相比较16.8版本肯定是更友好一些了, 实现同样的效果,一个执行两次,一个执行一次,效率更高,耗费资源更少,时间更短。
v18.2.0
这个版本有些特殊,因为有两种实现方式,输出还不一样,下面就来看看到底有些啥区别。
其一:18.2.0 与之前16.8.0, 17.0.0版本代码没啥区别,唯一区别仅仅是 react 和 react-dom 版本不同而已,还有就是在控制台有官方标红提示,表示18以后的版本不再对ReactDOM.render()函数支持,让切换使用ReactDOM.createRoot()函数,否则就会降低至17版本。
其二:18.2.0新增并发模式。最大的一个更新就是将以前的 ReactDOM.render() 替换成 ReactDOM.createRoot().render() 函数, 将彻底改变 React 的核心流程。
import {createRoot} from 'react-dom/client';
// 或
import ReactDOM from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
// 或
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
上面的代码需要注意,如果在程序中直接这么写是会报错的,这里仅仅是为了效果展示而已,正式使用的时候取其一即可。
通过上面的示例运行结果:
- 多出了clean
- 每一个组件都被 mount 了两次
- 子组件的 useEffet() 首先依次执行,然后执行父组件的useEffect(),这里顺序和之前并没有不同
- 子组件的 clean 执行,然后父组件的 clean 也执行,顺序和 useEffect() 执行顺序一致
为什么clean会执行,这是因为 React 18 并发模式下让组件强制更新一次,也就是 clean->effect ,并且会先整体把所有组件清理一遍,再执行所有组件的useEffect()副作用,而不是组件交替着一个个去执行,是不是有种先把所有相关数据给初始化后再去赋值展示的感觉。
最后,如果这篇笔记对你有所帮助,请帮忙点个赞(o( ̄▽ ̄)d)
,如果有问题,也请评论区指正。