useLayoutEffect
面试速答(30 秒版 TL;DR)
useLayoutEffect和useEffect都是副作用 Hook,但执行时机更早。- 它会在 DOM 提交后、浏览器绘制前 同步执行,适合做:
- 布局测量
- 立即同步样式
- 避免首帧闪烁
- 因为它会阻塞浏览器绘制,所以不要把普通请求和重逻辑放进去。
- 面试里一句话区分:要测量布局/防闪烁用
useLayoutEffect,普通副作用优先useEffect。
1. 它和 useEffect 最大的区别
两者都发生在 render 之后,但执行窗口不同:
useLayoutEffect:提交后、绘制前useEffect:提交后,通常不阻塞绘制
所以 useLayoutEffect 更像在浏览器真正把画面展示出来前,给你一个“最后同步修正”的机会。
2. 典型场景
2.1 读取布局信息
useLayoutEffect(() => {
const rect = ref.current?.getBoundingClientRect()
setWidth(rect?.width ?? 0)
}, [])
2.2 避免闪烁
例如:
- 先测量再决定 tooltip 方向
- 先拿尺寸再计算元素定位
如果放 useEffect,页面可能已经先绘制错误位置,再跳一下。
3. 为什么不能滥用
因为它是同步执行的,会阻塞绘制。
如果你在里面做:
- 大计算
- 发请求
- 复杂循环
用户首帧体验就可能变差。
4. React 18 下的注意点
4.1 开发环境 StrictMode
和普通 effect 一样,开发环境下也会有额外的挂载清理检查流程,所以仍要保证:
- 副作用可重复进入
- cleanup 完整
4.2 SSR 警告语境
在服务端环境里没有真实布局可读,所以涉及 SSR 时,社区里常见做法是:
- 客户端再执行
- 或做
useIsomorphicLayoutEffect封装
面试里只要说清:它本质依赖浏览器布局阶段,天然更偏客户端。
5. 面试高频答法
Q1:useEffect 和 useLayoutEffect 怎么选?
- 普通请求、订阅、日志、副作用同步:优先
useEffect - 读布局、改同步样式、避免视觉闪动:用
useLayoutEffect
Q2:为什么它能避免闪烁?
因为它发生在浏览器绘制前,你可以先测量、先修正,再让用户看到最终结果。
Q3:为什么说它不能随便用?
因为它阻塞绘制。用多了会把首帧和交互响应拖慢。
常见追问
1)它能替代 useEffect 吗?
技术上很多事都能写进去,但语义和性能上都不合适,不建议。
2)它适合请求数据吗?
不适合。请求不是“必须在绘制前同步完成”的事情。
易错点/坑
- 把所有 effect 都升级成
useLayoutEffect。 - 在里面写重逻辑,阻塞首帧绘制。
- 不知道它在 SSR 语境下的局限。
速记要点(可背诵)
useLayoutEffect:提交后、绘制前,同步执行。- 适合布局测量和防闪烁,不适合普通请求。
- 默认优先
useEffect,只有明确需要“绘制前同步处理”时才上useLayoutEffect。