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

相关推荐
咚咚咚ddd几秒前
前端组件:pc端通用新手引导组件最佳实践(React)
前端·react.js
Lazy_zheng1 分钟前
🚀 前端开发福音:用 json-server 快速搭建本地 Mock 数据服务
前端·javascript·vue.js
HJ_Coder1 分钟前
基于Proxyman的实时解密和预览方案
前端
Gixy2 分钟前
聊聊纯函数与不可变数据结构
前端·设计模式
ZzMemory2 分钟前
藏起来的JS(四) - GC(垃圾回收机制)
前端·javascript·面试
lsustc2 分钟前
让AI 帮我写一篇前端技术文章 一(Element Plus 主题编辑器)
前端
ChaselHi4 分钟前
G2Plot图表库——桑基图开发
前端
LuckySusu6 分钟前
【HTML篇】HTML 语义化标签:构建更清晰的网页结构
前端·html
林太白6 分钟前
前端必会之Nuxt.js
前端·javascript·vue.js
晓晓莺歌12 分钟前
vue-router路由问题:可以通过$router.push()跳转,但刷新后又变成空白页面
前端·javascript·vue.js