之前做一个需求,发现存在二次渲染的情况。在这里记录一下
useEffect
与
useLayoutEffect
的区别
先看一段代码
打印顺序是什么?
各位小伙伴可以先自行猜想一下。
useEffect
官方定义
在函数组件主体内(这里指在 React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。
通俗点来说
useEffect 其实就是让函数组件拥有了生命周期。
useEffect的执行时机
官方定义
与
componentDidMount
、
componentDidUpdate
不同的是,传给
useEffect
的函数会在浏览器完成布局与绘制
之后
,在一个延迟事件中被调用。这使得它适用于许多常见的副作用场景,比如设置订阅和事件处理等情况,因为绝大多数操作不应阻塞浏览器对屏幕的更新。
通俗点来讲
不论在面试中,还是工作中。如果有人问你
useEffect
是如何模拟生命周期的。你都会不假思索的回答出
-
第二个参数传递一个空数组, 模拟
componentDidMount
-
第二个参数传递依赖项,模拟
componentDidUpdate
-
第二个参数传递一个空数组,并且里面通过return的形式去调用一个方法,模拟
componentWillUnmount
但是
useEffect
的执行顺序问题,你有想到吗?如果父组件和子组件同时存在
useEffect
究竟是谁先走?
看一段代码
结果
为什么子组件的
useEffect
先走?
分析
我们都值得
useEffect
的执行是在
commit
之后,React的
commit
阶段是干什么的?简单来说,就是将DOM渲染到页面上。那么我们是否可以想到,
useEffect
其实是在页面已经渲染结束后,再触发的?
按照这个执行逻辑来看的话:
-
父组件进入
commit
阶段,发现有
Son
组件需要渲染。
-
开始进行
Son
的生命周期,
Son
进入
commit
阶段,执行子组件的
useEffect
,
Son
渲染结束
-
父组件进行
commit
阶段,渲染完成,执行
useEffect
useLayoutEffect
官方定义
其函数签名与
useEffect
相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,
useLayoutEffect
内部的更新计划将被同步刷新
通俗来讲
useLayoutEffect
与
componentDidMount
是同步执行的。在
commit
阶段之前执行,执行顺序优于
useEffect
执行顺序
useEffect 与 useLayoutEffect 的区别
useEffect 更改值
-
好处
不阻塞浏览器屏幕的渲染更新
-
坏处
会造成二次渲染,用户体验不佳
不会做动图。。。。各位大佬自己试一下。。。
会闪烁一下,页面首先展示的是
初始值
,点击
初始值
,先更改为
我改变了
,再更改为
我又改变了?
对用户的体验很不好。
useLayoutEffect 更改值
-
好处
随
componentDidMount
同步执行,不会造成二次渲染
-
坏处
可能会阻塞浏览器屏幕的渲染更新
页面首先展示的是
初始值
,点击
初始值
,更改为
我又改变了
最初代码的执行图
可能理解比较浅。后续有更好的理解会修改此文