内容目录
businessfragmentation
useLayoutEffect
是 React 中的一个 Hook,用于在浏览器重新绘制屏幕之前触发,与 useEffect 类似。
用法
import {useLayoutEffect} from 'react'
useLayoutEffect(() => {
// 副作用代码
return () => {
// 清理代码
}
}, [dependencies]);
参数
- setup:Effect处理函数,可以返回一个清理函数。组件挂载时执行setup,依赖项更新时先执行cleanup再执行setup,组件卸载时执行cleanup。
- dependencies(可选):setup中使用到的响应式值列表(props、state等)。必须以数组形式编写如 dep1, dep2 。不传则每次重渲染都执行Effect。
返回值
useLayoutEffect 返回undefined
useEffect
vs useLayoutEffect
对比
特性 | useEffect | useLayoutEffect |
---|---|---|
执行时机 | 在浏览器 绘制完成后 异步执行(不阻塞渲染) | 在浏览器 绘制前 同步执行(会阻塞渲染) |
执行阶段 | 属于 渲染提交阶段后的副作用(Commit Phase 之后) | 属于 渲染提交阶段中的副作用(Commit Phase 中,DOM 更新后、绘制前) |
对 DOM 修改的影响 | 若修改 DOM,用户可能看到闪烁(先渲染旧状态,再更新) | 修改 DOM 时,用户看不到中间状态(更新在绘制前完成) |
典型使用场景 | 数据获取、订阅、手动 DOM 操作(无需即时反馈) | 需要同步读取/修改 DOM(如测量元素尺寸、调整布局、避免闪烁的动画) |
类组件对应方法 | componentDidMount + componentDidUpdate + componentWillUnmount | componentDidMount + componentDidUpdate (但执行时机更早) |
性能影响 | 异步执行,不阻塞渲染,适合大多数场景 | 同步执行,可能阻塞渲染,过度使用会导致性能问题 |
// 使用 useEffect(可能看到闪烁)
useEffect(() => {
const element = document.getElementById("my-element");
if (element) element.style.height = "100px";
}, [deps]);
// 使用 useLayoutEffect(无闪烁)
useLayoutEffect(() => {
const element = document.getElementById("my-element");
if (element) element.style.height = "100px";
}, [deps]);
关键区别详解
执行时机
<font style="color:#000000;">useEffect</font>
:在 React 完成 DOM 更新 并触发浏览器绘制后异步执行,用户会先看到更新后的界面,再执行副 作用(可能伴随二次渲染)。
<font style="color:#000000;">useLayoutEffect</font>
:在 React 更新 DOM 但浏览器尚未绘制前同步执行,用户看到的界面已经是最终状态
适用场景
优先使用 **<font style="color:#000000;">useEffect</font>**
:大多数副作用(如 API 请求、日志记录、非紧急 DOM 操作)。
必须使用 **<font style="color:#000000;">useLayoutEffect</font>**
:当需要同步读取或修改 DOM(如测量元素尺寸、调整布局、避免视觉闪烁)。
// 示例:避免元素尺寸变化导致的闪烁
useLayoutEffect(() => {
const element = document.getElementById("my-element");
if (element) element.style.height = "100px";
}, [deps]);
性能开销
<font style="color:#000000;">useEffect</font>
更高效,因为异步执行不会阻塞浏览器渲染流程。
<font style="color:#000000;">useLayoutEffect</font>
可能导致性能瓶颈(同步执行阻塞渲染)导致浏览器渲染阻塞,需谨慎使用。
代码示例对比
场景:修改 DOM 元素尺寸
import React,{useEffect,useLayoutEffect} from 'react'
// 使用 useEffect(可能看到闪烁)
useEffect(() => {
const element = document.getElementById("my-element");
if (element) element.style.height = "100px";
}, [deps]);
// 使用 useLayoutEffect(无闪烁)
useLayoutEffect(() => {
const element = document.getElementById("my-element");
if (element) element.style.height = "100px";
}, [deps]);
总结
场景 | 推荐 Hook |
---|---|
数据获取、订阅、非紧急操作 | useEffect |
同步 DOM 读写、布局调整、防闪烁 | useLayoutEffect |