当前位置: 首页 > news >正文

react useEffect Hook讲解

什么是 useEffect Hook?

useEffect 是 React 中的一个 Hook,用于在函数组件中处理副作用(side effects)。副作用是指那些不在组件渲染过程中直接发生的事情,比如:

  • 发起网络请求(比如从服务器获取数据)
  • 操作 DOM(比如改变页面标题)
  • 设置定时器(比如 setTimeout 或 setInterval)
  • 订阅外部数据源(比如 WebSocket)

简单来说,useEffect 让你在组件渲染后(或某些特定时机)执行一些额外的操作。

useEffect 的基本语法

useEffect 是一个函数,接收两个参数:

  1. 回调函数:定义你要执行的副作用逻辑。
  2. 依赖数组(可选):控制副作用何时运行。

基本结构如下:

import { useEffect } from 'react';function MyComponent() {useEffect(() => {// 这里写副作用代码console.log('副作用执行了!');}, [/* 依赖项 */]);return <div>我的组件</div>;
}
  • 回调函数:每次组件渲染后(或依赖项变化时),这里面的代码会运行。
  • 依赖数组:告诉 React 什么时候需要重新运行回调函数。如果不传依赖数组,副作用每次渲染都会运行。

useEffect 的三种运行时机

根据依赖数组的不同,useEffect 的运行时机有以下三种情况:

1. 没有依赖数组

如果不提供依赖数组,副作用会在每次组件渲染后都运行。

useEffect(() => {console.log('组件每次渲染都会运行我!');
});

适用场景:很少用,因为每次渲染都运行副作用可能会导致性能问题。

2. 空依赖数组 []

如果提供一个空的依赖数组,副作用只在组件首次渲染后运行一次,类似于类组件中的 componentDidMount。

useEffect(() => {console.log('我只在组件首次渲染时运行!');
}, []);

适用场景

  • 初始化时获取数据(比如从 API 加载数据)
  • 设置一次性的事件监听器

3. 有依赖项的数组 [dep1, dep2, ...]

如果依赖数组中有变量,副作用会在组件首次渲染以及依赖项发生变化时运行。

import { useState, useEffect } from 'react';function MyComponent() {const [count, setCount] = useState(0);useEffect(() => {console.log(`count 变了,现在是 ${count}`);}, [count]);return (<div><p>计数: {count}</p><button onClick={() => setCount(count + 1)}>加1</button></div>);
}

运行逻辑

  • 首次渲染时,useEffect 运行。
  • 每次 count 变化时,useEffect 再次运行。
  • 如果 count 没变,即使组件重新渲染,useEffect 也不会运行。

适用场景

  • 根据状态或 props 变化执行副作用(比如根据用户 ID 获取用户信息)

useEffect 的清理函数

有时候,副作用需要清理,比如清除定时器、取消网络请求或移除事件监听器。useEffect 的回调函数可以返回一个清理函数,在组件卸载或副作用重新运行前执行。

useEffect(() => {const timer = setInterval(() => {console.log('计时器运行中...');}, 1000);// 返回清理函数return () => {clearInterval(timer);console.log('计时器被清理了!');};
}, []);

清理函数的运行时机

  • 组件卸载时(类似于 componentWillUnmount)。
  • 如果有依赖数组,依赖项变化导致副作用重新运行前,清理函数会先执行。

适用场景

  • 清除定时器(setTimeout、setInterval)
  • 取消订阅(比如 WebSocket 或事件监听器)
  • 防止内存泄漏

常见使用场景

以下是一些 useEffect 的典型例子,帮助你理解它的实际用途。

1. 获取数据(API 请求)

import { useState, useEffect } from 'react';function UserList() {const [users, setUsers] = useState([]);useEffect(() => {fetch('https://api.example.com/users').then(response => response.json()).then(data => setUsers(data));}, []); // 空数组,只在首次渲染时请求return (<ul>{users.map(user => (<li key={user.id}>{user.name}</li>))}</ul>);
}

2. 动态更新页面标题

import { useState, useEffect } from 'react';function Counter() {const [count, setCount] = useState(0);useEffect(() => {document.title = `你点击了 ${count} 次`;}, [count]); // 依赖 count,每次 count 变化更新标题return (<div><p>计数: {count}</p><button onClick={() => setCount(count + 1)}>加1</button></div>);
}

3. 设置事件监听器

import { useEffect } from 'react';function WindowSize() {useEffect(() => {const handleResize = () => {console.log(`窗口大小: ${window.innerWidth} x ${window.innerHeight}`);};window.addEventListener('resize', handleResize);// 清理事件监听器return () => {window.removeEventListener('resize', handleResize);};}, []); // 空数组,只在首次渲染时设置监听器return <div>调整窗口大小试试!</div>;
}

注意事项(新手常见坑)

  1. 不要在 useEffect 中直接修改状态,可能导致无限循环

    useEffect(() => {setCount(count + 1); // 错误!会导致无限渲染
    }, [count]);
    

    解决办法:确保状态更新有条件控制,或者使用空依赖数组。

  2. 依赖数组要包含所有用到的变量 如果 useEffect 里的代码用到了某个状态或 props,但没在依赖数组中声明,可能会导致 bug。ESLint 的 react-hooks/exhaustive-deps 规则会帮你检查。

    useEffect(() => {console.log(count); // count 必须在依赖数组中
    }, [count]); // 正确
    
  3. 清理函数的重要性 如果不清理定时器或事件监听器,可能会导致内存泄漏,尤其是在组件频繁挂载/卸载时。

  4. 不要把 useEffect 当成普通函数 useEffect 是为副作用设计的,不要用它来处理渲染逻辑(比如直接修改 DOM 或计算值)。渲染逻辑应该放在组件函数体或 useMemo 中。

总结

  • useEffect 的作用:处理副作用,比如数据获取、DOM 操作、事件监听等。
  • 运行时机
    • 无依赖数组:每次渲染都运行。
    • 空数组 []:仅首次渲染运行。
    • 有依赖项 [dep1, dep2]:首次渲染 + 依赖项变化时运行。
  • 清理函数:返回一个函数来清理副作用,防止内存泄漏。
  • 常见场景:API 请求、更新标题、设置定时器或事件监听器。
http://www.gsyq.cn/news/13024.html

相关文章:

  • 2025海丰杯WP
  • 2025电线电缆厂家最新权威推荐榜:聚焦电线电缆实力企业,覆盖多场景需求助力精准选购
  • 9.27课后作业
  • 调度算法,上古三算法
  • 学位论文中 公式的插入,格式调整、编号以及引用
  • 复刻江协激光触发器
  • Linux云服务器如何手动配置DNS?
  • 第一章——概论 - AlgosEng
  • 野指针
  • 自己湿热内蕴出汗痒和岳母生病2天不洗澡发痒的不同-完美解释小孩为啥没那么容易痒
  • vue: ubuntu安装vue环境
  • golang实现ai聊天窗口
  • 图的分类法:解耦数据和图表类型
  • 完整教程:图解人工智能中的高等数学(python实现)---一元函数微分学
  • IDEA 2024的零卡死配置
  • 3.WPF - 依赖属性 - 实践
  • PyTorch详细安装指南与常见问题解决强大的方案
  • 图解KV Cache
  • [K230学习笔记] 00前言
  • [CEOI 2025] theseus 做题记录
  • 2025/9/27
  • C# Smart3D Plate Part零件形状提取
  • Momentum Gradient Descent(动量梯度下降)
  • 深入解析:深度解析 CUDA-QX 0.4 加速 QEC 与求解器库
  • ProjectLibre
  • 实用指南:iOS 26 兼容测试实战,机型兼容、SwiftUI 兼容性改动
  • 大中午记梦
  • Arbess从入门到实战(3) - 启用Arbess+GitLab实现Vue.js计划自动化部署
  • 【深度学习计算机视觉】07:单发多框检测(SSD) - 指南
  • MZOI 2025.9.27