likes
comments
collection
share

React:useEffect和useLayoutEffect区别?

作者站长头像
站长
· 阅读数 39

在React中,useEffectuseLayoutEffect是两个常用的钩子,它们用于在函数组件中处理副作用。这两个钩子有一些相似之处,但它们在执行时机和用途上有一些重要的区别。

useEffect

useEffect是在组件渲染到屏幕之后执行的。它不会阻塞浏览器绘制,意味着页面更新完成后再执行useEffect中的代码。

用途

  • 数据获取:从API获取数据并更新组件状态。
  • 订阅:设置订阅,如WebSocket连接或数据流订阅。
  • 事件监听:添加或移除事件监听器。
  • 清理副作用:在组件卸载或依赖变化时清理副作用。

示例

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

const ExampleComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 组件挂载后执行
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));

    // 清理函数在组件卸载时或依赖项变化时执行
    return () => {
      console.log('Cleaning up...');
    };
  }, []); // 依赖数组为空,只在组件挂载和卸载时执行

  return (
    <div>
      {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : 'Loading...'}
    </div>
  );
};

useLayoutEffect

useLayoutEffect是在所有DOM变更之后同步执行的。这意味着它会在浏览器绘制之前执行,可能会阻塞页面渲染,直到其完成。

用途

  • 读取DOM布局:读取DOM元素的布局信息,如尺寸和位置。
  • 同步DOM变更:同步地处理副作用,以确保在浏览器绘制之前完成。
  • 避免闪烁:在组件更新后立即执行操作,防止用户在屏幕上看到不一致的内容。

示例

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

const LayoutEffectComponent = () => {
  const [height, setHeight] = useState(0);
  const divRef = useRef(null);

  useLayoutEffect(() => {
    // 在浏览器绘制之前同步执行
    if (divRef.current) {
      setHeight(divRef.current.getBoundingClientRect().height);
    }
  }, [height]); // 当 height 变化时再次执行

  return (
    <div ref={divRef} style={{ height: `${height}px`, background: 'lightblue' }}>
      The height of this div is: {height}px
    </div>
  );
};

区别总结

  1. 执行时机

    • useEffect:在组件渲染到屏幕之后异步执行,不会阻塞浏览器绘制。
    • useLayoutEffect:在所有DOM变更之后同步执行,会阻塞浏览器绘制,直到其完成。
  2. 用途

    • useEffect:用于异步操作(如数据获取、订阅、事件监听)和不影响布局的副作用。
    • useLayoutEffect:用于需要同步执行的操作(如读取DOM布局、同步DOM变更)和防止布局闪烁的副作用。
  3. 性能影响

    • useEffect:性能友好,因为它不会阻塞浏览器绘制。
    • useLayoutEffect:可能会影响性能,因为它会阻塞浏览器绘制,直到其完成。

何时使用

  • 使用useEffect:大多数副作用处理应该使用useEffect,因为它不会阻塞浏览器的绘制,并且通常不会影响用户体验。
  • 使用useLayoutEffect:在需要同步处理DOM操作且必须在浏览器绘制之前完成的情况下使用useLayoutEffect,例如读取布局信息或防止内容闪烁。

实践中的选择

在实践中,推荐默认使用useEffect,只有在确实需要同步处理DOM并避免布局闪烁的情况下,才使用useLayoutEffect。这有助于确保良好的性能和用户体验,同时减少不必要的复杂性和潜在的性能问题。

转载自:https://juejin.cn/post/7380994802744754213
评论
请登录