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,可以管理组件的生命周期和副作用逻辑。

相关推荐
先吃饱再说1 分钟前
React 组件通信:从 Props 单向传递到自定义事件
前端·react.js·前端框架
swipe6 分钟前
05|(前端转后全栈)不手写一堆 SQL,后端怎么操作数据库?MyBatis-Plus 入门
前端·后端·全栈
swipe10 分钟前
04|(前端转后全栈)前端状态为什么不够用?从页面数据到 MySQL 持久化
前端·后端·全栈
橘子星11 分钟前
别光看教程!手把手拆解 React Todo 项目,一文吃透 5 个核心概念
前端·javascript
大白要努力!17 分钟前
纯前端实现 PDF 加水印工具 —— 零后端、支持中文、实时预览
前端·pdf·html
石小石Orz19 分钟前
TRAE SOLO实战:实现一个桌面3D助手
前端·人工智能
蜡台25 分钟前
使用 uni-popup 实现数据选择器Data-Picker
前端·javascript·html·uniapp·uni-popup·data-picker
拆房老料26 分钟前
BaseMetas FileView 1.2.0 发布:Office/WPS 大文件预览与内存安全优化实测
前端·产品运营·开源软件
blns_yxl29 分钟前
Promise封装Fetch + 重试机制(HTML+JS)
前端·javascript·html
Elastic 中国社区官方博客34 分钟前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
大数据·运维·前端·人工智能·elasticsearch·搜索引擎·全文检索