`useLayoutEffect` 和 `useEffect`区别与联系
🌟 样式一:对比表格(加粗核心差异)
对比维度 | useEffect | useLayoutEffect |
---|---|---|
执行时机 | 浏览器绘制后(异步) | 🔥 浏览器绘制前(同步) |
阻塞渲染 | ❌ 不阻塞 | ⛔️ 阻塞,直到代码执行完毕 |
适用场景 | 数据请求、订阅等非紧急操作 | 📏 DOM 测量/同步修改(防闪烁) |
SSR 兼容性 | ✅ 安全 | ⚠️ 代码不会在服务端执行 |
性能风险 | 低 | 🔴 高(长任务会卡住页面) |
📊 样式二:流程图(执行顺序可视化)
React 组件更新│├─ 1. 渲染阶段(计算新虚拟DOM)│├─ 2. 提交阶段(更新真实DOM)│├─ 3. 【useLayoutEffect】执行 🔼 同步!阻塞绘制!│├─ 4. 浏览器绘制页面(Paint)│└─ 5. 【useEffect】执行 🔽 异步,不阻塞
重点学习:useLayoutEffect
卡在步骤3,必须执行完才让用户看到页面!
📝 样式三:分步选择指南(决策树)
-
是否需要操作 DOM 或测量布局?
• 是 → 进入第2步
• 否 → 用useEffect
-
操作是否会导致用户看到中间状态(如闪烁)?
• 是 → 🔥 选 useLayoutEffect
• 否 → 用useEffect
-
是否在服务端渲染(SSR)环境?
• 是 → 避免useLayoutEffect
(用useEffect
或条件执行)
• 否 → 可安全使用
🛠 样式四:代码对比(高亮关键差异)
场景:动态调整元素宽度
// 错误示例:使用 useEffect 可能导致闪烁
function Component() {useEffect(() => {// ❌ 用户可能先看到未调整的宽度element.style.width = calculateWidth();}, []);return <div ref={element} />;
}// 正确示例:useLayoutEffect 确保同步调整
function Component() {useLayoutEffect(() => {// ✅ 在绘制前完成,用户无感知element.style.width = calculateWidth();}, []);return <div ref={element} />;
}
重点标注:useEffect
的代码会导致视觉抖动,而 useLayoutEffect
消除闪烁!
🚨 样式五:注意事项清单(⚠️ 红色警报)
• useLayoutEffect
的雷区:
• 避免在内部执行耗时计算(如循环),会严重阻塞用户体验!
• SSR 场景下会触发警告,需用 typeof window !== 'undefined'
包裹。
• useEffect
的陷阱:
• 若依赖项变化频繁,可能引发性能问题(需配合防抖/节流)。
• 在卸载时清理副作用(如取消订阅),防止内存泄漏。
🎯 样式六:一句话总结(图标强化记忆)
• 🕒 useEffect
→ “Paint First, Code Later”(页面先出来,逻辑慢慢跑)
• ⚡ useLayoutEffect
→ “Code Now, Paint Later”(不让我改完,谁都别想看!)
通过多种样式的对比和重点标注,可以更立体地掌握两者的核心差异。实际开发中,优先考虑 useEffect
,仅在必须同步操作 DOM 时才谨慎使用 useLayoutEffect
! 🚀