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