useEffect vs useLayoutEffect:经典但持续被问,新版解读角度
useEffect vs useLayoutEffect:经典但持续被问,新版解读角度
导语
很多前端同学对 useEffect 和 useLayoutEffect 的第一反应是:一个异步,一个同步。这个答案在面试里能过,但在生产里经常被误用。本文从 React 源码执行阶段出发,给你一个更可落地的判断标准。
执行时机的本质区别
React 函数组件的渲染可以拆成三个阶段:Render 阶段、Commit 阶段(commitBeforeMutationEffects 执行 useLayoutEffect、commitLayoutEffects 执行 useEffect)。更准确的说法不是异步/同步,而是:useLayoutEffect 阻塞浏览器绘制;useEffect 不阻塞。
什么时候必须用 useLayoutEffect?
只有一种情况你需要它:读取 DOM 布局后同步触发重渲染,且不能接受闪烁。典型场景:测量 DOM 尺寸后立即设置状态、程序化滚动/聚焦、第三方库需要你在 DOM 更新后立即读取布局信息。
一个容易踩的坑:useLayoutEffect + SSR
useLayoutEffect 在服务端渲染时会发出警告,因为服务端没有 DOM。如果需要 SSR 兼容,可以降级为 useEffect。
结论:一个可落地的判断标准
- 默认用 useEffect:数据获取、事件监听、清理定时器……绝大多数副作用都归这里。
- 只有当你需要读 DOM → 立即写 DOM/状态且不能有闪烁时,才用 useLayoutEffect。
- 如果用了 useLayoutEffect 导致掉帧:检查里面有没有耗时计算,有的话拆到 Web Worker 或降级为 useEffect。
React 19 并没有改变这两个 Hook 的执行语义,但这个判断标准在并发渲染下更重要——因为并发渲染让浏览器绘制时机变得更不可预测,不阻塞绘制 becomes a feature, not a bug。
评论区
0 条评论
登录后可评论。












