前端 - React - - useEffect和useLayoutEffect的区别

前端 - React - - useEffect和useLayoutEffect的区别 useEffect和useLayoutEfeect都是处理副作用函数他俩的区别是在执行时间与事件机制上。1. 核心区别useEffect异步执行在浏览器绘制完成之后异步执行。它不会阻塞浏览器的视觉更新适合用于获取数据、事件绑定、日志记录等不直接影响当前帧 UI 的操作。useLayoutEffect同步执行在浏览器绘制之前同步执行。它会阻塞浏览器的渲染直到回调执行完毕。适合用于需要直接操作 DOM 样式、测量 DOM 尺寸且需要避免 UI 闪烁的场景。2. 分步分析执行时机为了直观理解我们看一下 React 组件更新时的完整时间线触发更新State 或 Props 改变。Render 阶段React 执行组件函数计算 Virtual DOM。Commit 阶段React 将 Virtual DOM 变更映射到真实的 DOM 节点此时 DOM 已更新但屏幕尚未绘制。useLayoutEffect执行同步阻塞React 在此处立即执行所有useLayoutEffect回调。浏览器绘制Paint浏览器终于将 DOM 节点绘制到屏幕上变成像素。useEffect执行异步React 在浏览器绘制完成后利用requestIdleCallback或微任务机制延迟执行useEffect回调。核心结论useLayoutEffect执行时你可以拿到最新的 DOM 节点但屏幕还是旧的还没画useEffect执行时屏幕已经变成新的了。常见问题使用useEffect时会出现页面闪烁问题假设你有一个组件渲染时依赖某个 DOM 节点的宽度且该宽度需要动态计算后设置高度。如果用useEffect错误示例function BrokenComponent() { const ref useRef(); useEffect(() { const height ref.current.getBoundingClientRect().width; ref.current.style.height ${height}px; // 修改 DOM }, []); return div ref{ref}内容/div; }页面会先渲染旧的高度比如高度为0然后瞬间“跳”到计算后的新高度。用户会看到明显的抖动或闪烁。如果用useLayoutEffect正确示例function FixedComponent() { const ref useRef(); useLayoutEffect(() { const height ref.current.getBoundingClientRect().width; ref.current.style.height ${height}px; }, []); return div ref{ref}内容/div; }React 在绘制前就修改了高度浏览器绘制时直接使用了最终尺寸用户看到的是稳定且平滑的界面。注意在 SSR 环境下服务端渲染useLayoutEffect会抛出警告Warning:useLayoutEffectdoes nothing on the server。因为在服务端没有 DOM 和 Paint 的概念React 会自动降级为useEffect。