两者都运行效果,但在 — 而这个时机差异就是关键所在。
两者都运行效果,但在 — 而这个时机差异就是关键所在。
useEffect 在浏览器绘制之后运行。它是异步且非阻塞的。将其用于几乎所有东西(数据、订阅、日志)。useLayoutEffect 在 DOM 发生变化之后但在浏览器绘制之前同步运行。当您需要读取布局并在同一帧中改变 DOM 以避免明显闪烁时,使用它。render → DOM updated → [useLayoutEffect runs] → browser paints → [useEffect runs]
想象测量一个元素并根据其大小重新定位工具提示。使用 useEffect 时,用户会短暂看到工具提示在错误的位置,然后它跳转:
useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect();
setTooltipTop(-height); // applied BEFORE paint → no visible jump
}, []);
使用 useEffect 时,相同的代码在绘制之后运行 → 产生一帧的闪烁。
useLayoutEffect 中进行繁重工作会使 UI 感到卡顿,因为浏览器在完成之前无法绘制。经验法则:默认使用 useEffect;仅对会否则导致闪烁的同步 DOM 测量/变化使用 useLayoutEffect。