学习React-13-useLayoutEffect
useLayoutEffect
useLayoutEffect 是 React 中的一个 Hook,与 useEffect 类似,但执行时机不同。它在
DOM 更新后
、浏览器绘制前同步执行
,适合需要直接操作 DOM 或测量布局的场景。
语法&参数
useLayoutEffect(() => {// 副作用逻辑return () => {// 清理逻辑(可选)};
}, [dependencies]);
参数
-
setup:Effect处理函数,可以返回一个清理函数。组件挂载时执行setup,依赖项更新时先执行cleanup再执行setup,组件卸载时执行cleanup。
-
dependencies(可选):setup中使用到的响应式值列表(props、state等)。必须以数组形式编写如[dep1, dep2]。不传则每次重渲染都执行Effect。
返回值
useLayoutEffect 返回 undefined
useEffect 与useLayuiEffect 对比
Hook | 执行时机 |
---|---|
useEffect | 浏览器绘制完成后异步执行 (不会阻塞 paint) |
useLayoutEffect | 浏览器绘制前同步执行 (会阻塞 paint) |
典型场景
- 测量 DOM 尺寸/位置(例如 Tooltip、Popover 需要定位)
- 防止闪烁:在浏览器绘制前把样式/位置调整好,用户看不到中间状态
- 其他需要同步修改 DOM 才能继续渲染的场景
小栗子
测试堵塞DOM
import React, { useLayoutEffect, useEffect, useState } from 'react';
function App() {const [count, setCount] = useState(0)//不阻塞DOMuseEffect(() => {for (let i = 0; i < 10000; i++) {//console.log(i);setCount(count => count + 1)}}, []);//阻塞DOM// useLayoutEffect(() => {// for (let i = 0; i < 10000; i++) {// //console.log(i);// setCount(count => count + 1)// }// }, []);return (<div><div>app </div>{Array.from({ length: count }).map((_, index) => (<div key={index}>{index}</div>))}</div>);
}
export default App;
效果对比:
使用useEffect
使用useLayoutEffect
结果很明显,使用useEffect并没有因为动态加载元素而阻止页面元素静态app的渲染,而使用useLayoutEffect则会等待元素全部准备好之后一起渲染,这样当网络不稳定或者数据量大的时候就会导致页面白屏。
测试异步同步渲染
import './inde