跳到主要内容

useLayoutEffect

面试速答(30 秒版 TL;DR)

  • useLayoutEffectuseEffect 都是副作用 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:useEffectuseLayoutEffect 怎么选?

  • 普通请求、订阅、日志、副作用同步:优先 useEffect
  • 读布局、改同步样式、避免视觉闪动:用 useLayoutEffect

Q2:为什么它能避免闪烁?

因为它发生在浏览器绘制前,你可以先测量、先修正,再让用户看到最终结果。

Q3:为什么说它不能随便用?

因为它阻塞绘制。用多了会把首帧和交互响应拖慢。

常见追问

1)它能替代 useEffect 吗?

技术上很多事都能写进去,但语义和性能上都不合适,不建议。

2)它适合请求数据吗?

不适合。请求不是“必须在绘制前同步完成”的事情。

易错点/坑

  • 把所有 effect 都升级成 useLayoutEffect
  • 在里面写重逻辑,阻塞首帧绘制。
  • 不知道它在 SSR 语境下的局限。

速记要点(可背诵)

  • useLayoutEffect:提交后、绘制前,同步执行。
  • 适合布局测量和防闪烁,不适合普通请求。
  • 默认优先 useEffect,只有明确需要“绘制前同步处理”时才上 useLayoutEffect