如何在 React 中正确地使用 useEffect 处理组件卸载时的清理操作以避免内存泄漏?

如何在 React 中正确地使用 useEffect 处理组件卸载时的清理操作以避免内存泄漏?

在 React 中,useEffect Hook 可以返回一个清理函数,该函数会在组件卸载前或下一次 effect 执行前被调用。这是避免内存泄漏(如未取消的异步请求、定时器或事件监听器)的关键机制。

示例代码:

import { useEffect, useState } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    let isMounted = true; // 标记组件是否仍挂载

    const fetchData = async () => {
      const result = await fetchSomeData();
      if (isMounted) {
        setData(result);
      }
    };

    fetchData();

    // 清理函数
    return () => {
      isMounted = false; // 组件卸载时取消状态更新
    };
  }, []);

  return <div>{data ? data : 'Loading...'}</div>;
}

解析:

  1. 清理函数的作用:useEffect 返回的函数会在组件卸载时自动执行,也可用于清除上一次 effect 的副作用(如 clearTimeout、removeEventListener 等)。
  2. 避免异步回调中的状态更新:如果组件在异步操作完成前卸载,调用 setState 会触发 React 警告甚至潜在错误。通过 isMounted 标志可安全判断是否仍可更新状态。
  3. 替代方案:对于更复杂的场景(如 Axios 请求),可使用 AbortController 取消请求:
useEffect(() => {
  const controller = new AbortController();

  fetch('/api/data', { signal: controller.signal })
    .then(res => res.json())
    .then(data => setData(data))
    .catch(e => {
      if (e.name !== 'AbortError') console.error(e);
    });

  return () => {
    controller.abort(); // 取消请求
  };
}, []);

总结:合理使用 useEffect 的清理函数是保障 React 应用健壮性和避免内存泄漏的最佳实践。

发表评论 (审核通过后显示评论):

昵称:
邮箱:
内容: