React useEffect 使用场景示例

React 的 useEffect 是用于处理副作用(如数据获取、订阅、手动 DOM 操作等)的 Hook。以下是几个常见使用场景的示例:


1. 组件挂载时获取数据

jsx 复制代码
import { useEffect, useState } from 'react';

function DataFetcher() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // 定义一个异步函数
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();

    // 清理函数(可选,比如取消请求)
    return () => {
      // 可以在这里取消未完成的请求
    };
  }, []); // 空依赖数组:仅在组件挂载时运行一次

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      {data.map(item => <div key={item.id}>{item.name}</div>)}
    </div>
  );
}

2. 依赖项触发副作用

当某个值(如 count)变化时更新文档标题:

jsx 复制代码
function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]); // 依赖项为 count,当 count 变化时触发

  return (
    <button onClick={() => setCount(count + 1)}>
      Increment ({count})
    </button>
  );
}

3. 添加和移除事件监听器

监听窗口大小变化:

jsx 复制代码
function WindowSizeTracker() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    window.addEventListener('resize', handleResize);

    // 清理函数:组件卸载时移除事件监听
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组:仅在组件挂载和卸载时运行

  return (
    <div>
      Window size: {windowSize.width} x {windowSize.height}
    </div>
  );
}

4. 定时器(setInterval)

每秒更新一次时间:

jsx 复制代码
function Timer() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const timerId = setInterval(() => {
      setTime(new Date());
    }, 1000);

    // 清理函数:组件卸载时清除定时器
    return () => clearInterval(timerId);
  }, []); // 空依赖数组:定时器只初始化一次

  return <div>Current time: {time.toLocaleTimeString()}</div>;
}

5. 依赖项为空 vs 无依赖

  • 空依赖数组 []:仅在组件挂载时运行一次。
  • 无依赖数组:每次组件渲染后都会运行。
  • 特定依赖 [dep1, dep2]:当依赖项变化时运行。

注意事项

  1. 避免无限循环 :如果依赖项是引用类型(如对象或数组),需确保它们的引用稳定(比如使用 useMemo)。

  2. 异步操作 :直接在 useEffect 中使用 async 函数会报错,但可以在内部定义 async 函数并调用:

    jsx 复制代码
    useEffect(() => {
      const fetchData = async () => { /* ... */ };
      fetchData();
    }, []);
  3. 清理副作用:始终为需要清理的操作(如事件监听、定时器)返回清理函数。

通过合理使用 useEffect,可以管理组件的生命周期和副作用逻辑。

相关推荐
申朝先生13 分钟前
面试的时候问到了HTML5的新特性有哪些
前端·信息可视化·html5
在下千玦22 分钟前
#前端js发异步请求的几种方式
开发语言·前端·javascript
知否技术23 分钟前
面试官最爱问的Vue3响应式原理:我给你讲明白了!
前端·vue.js
小周同学:1 小时前
vue将页面导出成word
前端·vue.js·word
阿杰在学习1 小时前
基于OpenGL ES实现的Android人体热力图可视化库
android·前端·opengl
xfq1 小时前
[ai] cline使用总结(包括mcp)
前端·后端·ai编程
weiran19991 小时前
手把手的建站思路和dev-ops方案
前端·后端·架构
小刀飘逸2 小时前
子元素 margin-top 导致父元素下移问题的分析与解决方案
前端
Evrytos2 小时前
告别石器时代#2:ES6新数据类型
前端·javascript
Ody2 小时前
大屏开发适配方案全面解析
前端