React Academy · 课时

useLayoutEffect 与 useEffect 的运行时机

了解 useLayoutEffect 会在 DOM 变更后、浏览器绘制前同步触发

第 2 / 4 课13 个步骤

useLayoutEffect 与 useEffect 的运行时机 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

useLayoutEffect 的时序

useLayoutEffect 会在 React 应用 DOM 变更后立即同步触发,但此时浏览器还没有机会绘制这些变更。从浏览器的角度看,布局副作用和 DOM 变更属于同一个不间断的同步工作块。

useEffect 的时序

useEffect 会在浏览器完成绘制后异步触发。用户会先看到更新后的界面,然后副作用才会运行。这使得 useEffect 对渲染性能的干扰较小,但也意味着副作用导致的任何可见变化都会产生第二个绘制周期。

时间戳实验

您可以通过在两个副作用中记录时间戳来验证时序差异:在 useLayoutEffect 中添加 console.log('layout', Date.now()),并在 useEffect 中添加 console.log('passive', Date.now())。在控制台中,布局副作用的时间戳总是早于被动副作用的时间戳,从而确认执行顺序。

对用户可见的影响

如果 useEffect 更新了会影响视觉输出的状态,用户会看到两次渲染:第一次渲染使用过时的状态,副作用触发后再进行修正后的渲染。这会表现为可见的闪烁或重排。useLayoutEffect 可以避免这种情况,因为它的状态更新会在浏览器绘制任何内容之前提交。

useLayoutEffect 的状态更新会导致同步重新渲染

如果您在 useLayoutEffect 中调用 setState,React 会在绘制前立即运行另一个渲染和提交周期。浏览器只会绘制最终结果,用户永远不会看到中间状态。这正是 useLayoutEffect 的主要用途:测量 DOM、计算新值、设置状态,并确保只进行一次干净的绘制。

性能注意事项

由于 useLayoutEffect 会在绘制前同步运行,并且可能触发额外的渲染,过度使用会损害性能。如果同步工作负担过重,就会阻塞浏览器绘制,造成明显的卡顿。只有在需要防止视觉闪烁时才使用它;其他情况都应使用 useEffect。

严格模式中的双重调用

在 React 严格模式中(仅限开发环境),useLayoutEffect 和 useEffect 在每次挂载时都会被调用两次。顺序是:挂载、清理、再次挂载。这有助于检测未正确清理的副作用。生产构建不会发生双重调用。

性能规则:默认使用 useEffect

默认选择始终应当是 useEffect。只有在您能够观察并复现视觉闪烁或布局错误时,才切换到 useLayoutEffect。过度使用 useLayoutEffect 会不必要地阻塞浏览器的绘制流程,并降低用户感知到的性能。

SSR 注意事项:服务器上的 useLayoutEffect

useLayoutEffect 无法在服务器上运行,因为服务器环境中没有 DOM,也没有浏览器绘制周期。如果在会于服务器上渲染的组件中使用它,React 会发出警告。解决方法是有条件地跳过该副作用:检查 typeof window !== 'undefined',或者在兼容 SSR 的代码中改用 useEffect。

如何判断应该使用哪一个

请问自己:“这个副作用是否会改变用户在第一次绘制时看到的内容?”如果是,请使用 useLayoutEffect 来防止闪烁。如果不是——例如数据获取、订阅、数据分析、日志记录以及大多数其他副作用——请使用 useEffect。这一决策框架适用于大多数实际场景。

useLayoutEffect 的同步特性

useLayoutEffect 会与 DOM 变更运行在同一个同步工作块中。当 useLayoutEffect 正在运行时,React 无法处理其他任务,例如响应用户事件。这就是它必须快速且专注的原因。在 useLayoutEffect 中运行耗时较长的同步代码,会直接延迟浏览器将内容绘制到屏幕上。

useLayoutEffect 的时序

useLayoutEffect 相对于 DOM 变更和浏览器绘制,究竟会在什么时候触发?

课程回顾:useLayoutEffect 与 useEffect

useLayoutEffect 是同步的,会在浏览器绘制前触发,因此适合进行 DOM 测量和视觉修正。useEffect 会在绘制后触发,适合数据获取、订阅和大多数副作用。默认使用 useEffect,只有在视觉闪烁确认需要 useLayoutEffect 时才切换。未加防护时,不要在 SSR 中使用它。

免费开始

用 AI 导师学习 React — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
88
课程
324

常见问题解答

「useLayoutEffect 与 useEffect 的运行时机」课时是免费的吗?

是的 — 「useLayoutEffect 与 useEffect 的运行时机」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「useLayoutEffect 与 useEffect 的运行时机」这节课中我会学到什么?

了解 useLayoutEffect 会在 DOM 变更后、浏览器绘制前同步触发 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「useLayoutEffect 与 useEffect 的运行时机」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 渲染阶段与 DOM 提交
  2. useLayoutEffect 与 useEffect 的运行时机
  3. 使用 useLayoutEffect 测量 DOM 元素
  4. 避免布局抖动与视觉闪烁
← 返回 React Academy