React useLayoutEffect

966 阅读2分钟

在 React 中,useLayoutEffect 是一个钩子(Hook),与 useEffect 类似,它允许你在函数组件中执行副作用(side effects)。useLayoutEffect 的作用和 useEffect 很相似,但它在组件生命周期中的执行时机不同。

用途和用法:

useLayoutEffect 主要用于处理需要同步执行的副作用操作,特别是和 DOM 相关的操作,比如读取或修改 DOM 尺寸、位置等,因为 useLayoutEffect 在 DOM 更新后立即同步调用,且在浏览器进行任何绘制之前执行。这样可以在新的屏幕绘制发生前完成必要的 DOM 操作,避免可能的闪烁或不必要的重新绘制。

useLayoutEffect(() => {
  // 在 DOM 更新之后、绘制之前执行
  // 这里可以安全地读取 DOM 属性(比如计算样式)或执行更多的 DOM 更新
  
  return () => {
    // 清理或撤销副作用的代码
  };
}, [dependencies]); // 依赖项数组,只有依赖项改变时才会重新执行

示例:

import React, { useState, useLayoutEffect } from 'react';

function MyComponent() {
  const [value, setValue] = useState(0);
  
  useLayoutEffect(() => {
    if (value === 0) {
      setValue(Math.random() * 100);
    }
  }, [value]);

  return (
    <div>
      Value: {value}
    </div>
  );
}

在这个例子中,useLayoutEffect 在组件第一次渲染时同步执行,并在渲染后立即更新状态 value。由于 useLayoutEffect 在浏览器绘制前执行,用户看不到 value 初始值为 0 的状态,从而避免了闪烁。

使用注意事项:

  1. 不要滥用: 由于 useLayoutEffect 会在浏览器绘制前执行,滥用可能会导致性能问题。如果副作用操作和 DOM 更新无关,通常应使用 useEffect
  2. useEffect 对比: 如果不需要同步操作 DOM 或副作用操作对用户可见性没有要求,建议使用 useEffectuseEffect 会在布局和绘制之后的下一个浏览器绘制周期执行,不会阻塞浏览器的绘制。
  3. 执行时机: 由于 useLayoutEffect 在所有 DOM 变更之后立即执行,因此它可以用于读取新布局的信息而不会导致重绘。它的执行时机类似于类组件中的 componentDidMountcomponentDidUpdate 生命周期方法。
  4. 服务器端渲染: useLayoutEffect 不能在服务器端渲染(SSR)期间运行,如果在 SSR 期间使用 useLayoutEffect,React 会显示警告,并在客户端重新运行组件。因此,如果你的组件需要进行服务器端渲染,应该确保在服务器端使用 useEffect 并在客户端使用 useLayoutEffect
  5. 清理函数: 如果 useLayoutEffect 返回一个清理函数,这个清理函数会在组件卸载之前或下一个 useLayoutEffect 执行之前运行,用于清理或撤销副作用。这与 useEffect 中的清理机制相同。