React 提供了 useEffect 和 useLayoutEffect 这两个 hook 来执行 React 副作用,这两个 hook 在部分场景下功能一致,那么具体的差别是什么,接下来我们来探讨一下。
执行时机
useEffect
:在组件渲染(浏览器完成绘制)之后执行,属于异步触发,不会阻塞组件渲染。
useLayoutEffect
:组件在浏览器绘制之前触发,属于同步触发,会阻塞组件渲染。
执行性能
useEffect
:在绘制后执行,不会阻塞浏览器渲染,对性能影响较小。
useLayoutEffect
:在绘制前执行,如果在该副作用下执行复杂的操作,比如频繁调用 getBoundingClientRect, offsetHeight 等api,会导致不必要的重绘或者重排,影响性能。
代码示例
import React, { useState, useEffect, useRef } from 'react';
function ResizeAwareComponent() {
const ref = useRef(null);
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
// 这个effect会在组件渲染到屏幕之后执行,适合进行数据获取等操作
console.log('组件挂载');
}, []);
useLayoutEffect(() => {
// 这个effect会在DOM更新后,浏览器绘制之前执行,适合进行布局计算
if (ref.current) {
const { width, height } = ref.current.getBoundingClientRect();
setSize({ width, height });
}
}, []);
return (
<div ref={ref}>
Kelen.cc
</div>
);
}
使用场景
在大部分场景下,优先考虑使用 useEffect
,除非有需要在副作用下执行一些 DOM 操作防止页面闪烁或者抖动,比如一些动画,滚动交互等等,才考虑用 useLayoutEffect
。