useEffect 和 useLayoutEffect 的区别和用法

时间:2023-08-10 浏览:164 分类:React

先一句话总结:

useEffect 在浏览器完成布局和绘制后,异步执行副作用。这意味着,如果你的副作用会改变 DOM 结构或样式,用户可能会看到闪烁。

useLayoutEffect 在浏览器完成布局和绘制前,同步执行副作用。这意味着,如果你的副作用会改变 DOM 结构或样式,用户不会看到闪烁。


详细解释:

在 React 中,有两个 Hooks 可以用来在组件渲染后执行副作用:useEffect 和 useLayoutEffect。它们的用法非常相似,但是它们的执行时机不同。

useEffect

useEffect 是一个 Hook,它可以让你在函数组件中执行副作用。它的语法如下:

useEffect(() => {
  // 在这里执行副作用
}, [dependencies]);

useEffect 接受两个参数:一个副作用函数和一个依赖数组。副作用函数会在组件渲染后异步执行。依赖数组中的每一项都会被 React 跟踪,当其中任意一项发生变化时,副作用函数都会重新执行。

下面是一个简单的例子,演示如何使用 useEffect 来更新文档标题:

import { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}


在这个例子中,我们使用 useState Hook 来定义一个状态变量 count 和一个更新状态的函数 setCount。然后,我们使用 useEffect Hook 来定义一个副作用函数,它会在组件渲染后异步执行。在副作用函数中,我们更新文档标题,使其显示当前点击次数。

由于我们将 count 添加到了依赖数组中,所以每当 count 发生变化时,副作用函数都会重新执行,文档标题也会相应更新。

useLayoutEffect

useLayoutEffect 是另一个可以用来执行副作用的 Hook。它的语法和 useEffect 非常相似:

useLayoutEffect(() => {
  // 在这里执行副作用
}, [dependencies]);


与 useEffect 不同的是,useLayoutEffect 中的副作用函数会在浏览器完成布局和绘制前同步执行。这意味着,如果你的副作用会改变 DOM 结构或样式,用户不会看到闪烁。

下面是一个简单的例子,演示如何使用 useLayoutEffect 来避免闪烁:

import { useState, useLayoutEffect } from 'react';

function Example() {
  const [width, setWidth] = useState(0);

  useLayoutEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    handleResize();
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    <div>
      <p>Window width: {width}</p>
    </div>
  );
}


在这个例子中,我们使用 useState Hook 来定义一个状态变量 width 和一个更新状态的函数 setWidth。然后,我们使用 useLayoutEffect Hook 来定义一个副作用函数,它会在浏览器完成布局和绘制前同步执行。在副作用函数中,我们监听窗口大小变化事件,并更新状态变量 width。

由于我们使用了 useLayoutEffect 而不是 useEffect,所以当窗口大小发生变化时,状态变量 width 会立即更新,并且用户不会看到闪烁。

区别

那么,useEffect 和 useLayoutEffect 的区别到底是什么呢?

简单来说,它们的区别就在于执行时机不同。useEffect 在浏览器完成布局和绘制后异步执行副作用;而 useLayoutEffect 在浏览器完成布局和绘制前同步执行副作用。

这意味着,如果你的副作用会改变 DOM 结构或样式,使用 useEffect 可能会导致用户看到闪烁;而使用 useLayoutEffect 则不会。

但是,由于 useLayoutEffect 是同步执行的,所以它可能会阻塞浏览器渲染,导致性能问题。因此,在使用 useLayoutEffect 时应谨慎。

总结

useEffect 和 useLayoutEffect 都是 React Hooks,它们都可以用来在组件渲染后执行副作用。它们的用法非常相似,但是它们的执行时机不同。

通常情况下,你应该使用 useEffect。只有当你的副作用会改变 DOM 结构或样式,并且会导致用户看到闪烁时,才应该使用 useLayoutEffect。但是要注意,由于 useLayoutEffect 是同步执行的,所以它可能会阻塞浏览器渲染,导致性能问题。因此,在使用 useLayoutEffect 时应谨慎。