useEffect与useLayoutEffect对比
2025-12-02
1141 字约 4 分钟
...在 React Hooks 中,useEffect 和 useLayoutEffect 都用于处理副作用逻辑,例如订阅、事件监听、DOM 操作等。但它们有着本质性的执行时机差异,这影响到页面渲染、布局抖动、性能表现等关键点。
1. 执行时机的核心区别
在 React 的渲染流程中:
-
渲染(Render phase)
React 根据 state/props 计算 UI,生成虚拟 DOM,不访问真实 DOM。 -
提交(Commit phase)
React 将虚拟 DOM 变为真实 DOM,写入页面。
然后才触发 Hook 副作用:
useEffect — 异步、在浏览器绘制后执行
- 执行时机:浏览器完成渲染(paint)之后
- 异步执行,不会阻塞页面渲染
- 页面先更新 → 用户能立即看到 → 再执行 effect 回调
useLayoutEffect — 同步、在 DOM 更新但页面绘制前执行
- 执行时机:DOM 更新 → 浏览器绘制前
- 同步执行(blocking)
- React 会等待 useLayoutEffect 执行完,才允许浏览器绘制屏幕
2. 执行顺序图示
React Render → 真实 DOM 更新 → (useLayoutEffect) → 浏览器绘制 → (useEffect)
3. 执行时机对比表(GFM 表格)
| 阶段 | useLayoutEffect | useEffect |
|---|---|---|
| 渲染前(Render) | ❌ | ❌ |
| DOM 更新后(Commit) | ✔️(同步) | ❌ |
| 浏览器绘制前 | ✔️ | ❌ |
| 浏览器绘制后 | ❌ | ✔️(异步) |
4. useEffect 的典型使用场景
✔️ 异步请求
useEffect(() => {
fetch("/api/user").then(...)
}, []);
✔️ 订阅 / 事件监听
useEffect(() => {
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
✔️ 不依赖布局的逻辑
结论:只要不是 DOM 布局相关的副作用,都推荐使用 useEffect。
5. useLayoutEffect 的使用场景
✔️ 1. 读取 DOM 尺寸后同步修改
useLayoutEffect(() => {
const width = divRef.current.offsetWidth;
setWidth(width);
}, []);
✔️ 2. 动画初始状态控制
useLayoutEffect(() => {
element.style.opacity = 0;
requestAnimationFrame(() => {
element.style.transition = "opacity .3s";
element.style.opacity = 1;
});
}, []);
✔️ 3. 第三方 DOM 库(如 D3、GSAP、Swiper)
6. 总结对比(GFM 表格)
| 项目 | useEffect | useLayoutEffect |
|---|---|---|
| 执行时间 | 浏览器绘制后 | 浏览器绘制前 |
| 是否阻塞渲染 | ❌ | ✔️ |
| 是否用于 DOM 操作 | ❌ 不推荐 | ✔️ 推荐 |
| 使用场景 | 异步请求、事件、日志、状态 | DOM 布局、同步操作、动画初始化 |
| 官方建议 | 默认使用 | 仅必要时使用 |
一句话总结
useEffect:渲染后执行。
useLayoutEffect:渲染前必须执行。
绝大多数场景使用 useEffect,只有当副作用需要同步 DOM 时才使用 useLayoutEffect。
如果您觉得这篇文章有帮助,请点个赞吧~
相关文章
更多文章 →react2025-08-03
在 React 中实现倒计时功能会有什么坑
倒计时 倒计时是一个非常常见的业务场景,但是在 React 中实现起来,却不算简单。 首先我们来看这段倒计时代码,它能否正常执行? 来看看实际表现效果 可以看到计时器在不断执行,但是 的值却没有变。 这是一个很经典的问题:React 闭包陷阱 。 我们来详细分析下: 的依赖数组 是空的,这意味着 effect 只会在组件挂载时执行一次,而不会在 状态更新时重新执行。所以 回调函数中捕获的 值始终是初始值 。 这个问题解决起来也很简单,有...
学习面试
react2025-07-30
React性能优化三剑客:memo、useMemo和useCallback详解
前言 在React开发中,性能优化是一个永恒的话题。今天我们就来深入探讨React提供的三个重要性能优化工具: 、 和 ,它们如何帮助我们构建更高效的React应用。 1\. 为什么需要性能优化? 🤔 React的核心机制是当组件的state或props发生变化时,组件会重新渲染。但有时这种重新渲染是不必要的: 父组件更新导致所有子组件重新渲染 ,即使子组件的props没有变化 复杂计算在每次渲染时重复执行 ,消耗大量资源 函数引用在...
学习面试
react2025-06-05
React 中 useDeferredValue 和 startTransition 的核心区别与使用场景
React 中 和 ,两者都用于优化性能,但适用场景和实现方式不同。 核心概念解析 1\. useDeferredValue:延迟值更新 作用 :告诉 React 延迟更新某个值 ,直到所有高优先级渲染任务完成。 适用场景 :当某个值的更新会触发计算密集型渲染(如复杂列表、图表),但需要优先保证其他高优先级 UI(如输入框)的响应。 机制 : 保持旧值显示,后台计算新值。 计算完成后,用新值更新 UI,期间允许用户继续交互。 示例 :...
学习
react2024-12-18
Antd 样式覆盖
目前作者所在的业务正在升级 Antd5.0,不得不说 Antd5.0 真的太香了,但是由于团队的 UE 规范进行了大改版,Antd5.0 所有的 必须对齐最新的规范,因此就需要对 Antd5.0 组件做主题定制。 现状 目前针对项目中使用的 antd 高频组件进行了梳理,并且根据规范基于 design token 对这些高频组件进行样式定制,对于主题色、圆角、边框、字体等用户 高的主题都已经满足团队规范。 虽然 Desig...
学习
react2024-12-06
React 19 终于发布,一大波新功能正式升级
这篇文章主要介绍了 React 19 的新功能,包括 Actions 自动处理数据突变相关状态,新增的 useActionState、useFormStatus、useOptimistic 等 hook,新的 use API 读取渲染资源,新的 React DOM 静态 API 生成静态站点,以及 React 服务器组件中的 RSC 和 RSA 等内容。同时提到后续会分享针对旧版功能的优化和改良。 关联问题: React 19 性能如何...
学习面试
react2024-10-11
React表单:formik、final-form和react-hook-form
表单无处不在,它是每个网站的必备部分。在用React构建web应用时,处理表单是不可避免的。 你可以选择自己的方式来处理,或者选择社区中现成的库。然而,当你选择一个第三方库时,你会立即面临一个问题:有太多的库可供选择。 选择一个库是一件棘手的事情,随意选择一个GitHub上星标多的库并不总是明智的。你肯定需要阅读文档、代码示例,并多次尝试,才能确定这是你想要用于自己项目的库。 对于处理表单,我们有以下选择: | 库名称 | GitHub...
学习
评论
请登录后发表评论
去登录