useEffect使用方式及注意事项

news/2025/4/1 8:31:09/文章来源:https://www.cnblogs.com/liubenben/p/18800090

React useEffect 使用方式及注意事项

useEffect 是 React Hooks 中处理副作用的核心 API,用于替代类组件中的生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)。以下是其使用方式及关键注意事项:


一、基本使用方式

1. 语法

useEffect(() => {// 副作用逻辑return () => { /* 清理函数(可选)*/ };
}, [dependencies]);

2. 不同场景的使用

  • 每次都执行
    不传第二个参数,每次都执行:

    useEffect(() => {console.log('组件渲染时执行');
    });
    
  • 执行一次(挂载时)
    依赖数组为空,仅在组件挂载时执行:

    useEffect(() => {console.log('组件挂载时执行');fetchData(); // 数据请求
    }, []);
    
  • 依赖变化时执行
    当依赖项变化时,触发副作用:

    const [count, setCount] = useState(0);
    useEffect(() => {console.log('count变化时执行:', count);
    }, [count]); // 依赖 count
    
  • 清理副作用
    返回一个函数用于清理(如取消订阅、清除定时器):

    useEffect(() => {const timer = setInterval(() => {console.log('定时器运行');}, 1000);return () => clearInterval(timer); // 清理定时器
    }, []);
    

二、注意事项

1. 正确处理依赖数组

  • 依赖缺失:可能导致闭包问题(使用过期的变量)。

    // ❌ 错误:依赖缺失
    const [count, setCount] = useState(0);
    useEffect(() => {const timer = setInterval(() => {console.log(count); // 始终输出初始值 0}, 1000);return () => clearInterval(timer);
    }, []); // 缺少 count 依赖// ✅ 正确:添加依赖或使用函数式更新
    useEffect(() => {const timer = setInterval(() => {setCount(prev => prev + 1); // 通过函数式更新获取最新值}, 1000);return () => clearInterval(timer);
    }, []);
    
  • 依赖冗余:不必要的依赖可能导致频繁触发。
    建议:使用 ESLint 规则 react-hooks/exhaustive-deps 自动检测依赖。

2. 避免无限循环

当副作用内更新依赖的状态时,可能触发无限循环:

// ❌ 错误:每次更新 count 都会触发 effect
const [count, setCount] = useState(0);
useEffect(() => {setCount(count + 1); // 触发重新渲染,再次执行 effect
}, [count]); // ✅ 解决方案:确保更新是必要的,或使用空依赖
// 例如,仅在挂载时初始化
useEffect(() => {setCount(1);
}, []); 

3. 异步操作处理

useEffect 的回调函数不能直接使用 async,但可以内部定义异步逻辑:

// ✅ 正确:在 effect 内部定义异步函数
useEffect(() => {const fetchData = async () => {const res = await api.getData();setData(res);};fetchData();
}, []);// ✅ 或使用 IIFE(立即执行函数)
useEffect(() => {(async () => {const res = await api.getData();setData(res);})();
}, []);

4. 清理副作用

如果副作用需要清理(如订阅、定时器),必须返回清理函数:

useEffect(() => {const subscription = eventEmitter.subscribe(() => {});return () => subscription.unsubscribe(); // 清理订阅
}, []);

5. 执行时机

  • useEffect 在浏览器完成布局与绘制异步执行。
  • 若需同步执行(如测量布局),使用 useLayoutEffect

6. 开发环境下的严格模式

React 18+ 在开发模式下会重复挂载组件以检测副作用问题:

// 示例:effect 执行两次
useEffect(() => {console.log('Effect执行'); // 开发模式下输出两次
}, []);

解决方案:确保副作用和清理函数是幂等的(多次执行无副作用)。

7. 避免条件语句中使用 Hook

Hook 必须在组件顶层调用,不可嵌套在条件或循环中:

// ❌ 错误:条件语句中使用 useEffect
if (isLoaded) {useEffect(() => { /* ... */ }, []); 
}// ✅ 正确:将条件移至 effect 内部
useEffect(() => {if (isLoaded) {// 执行逻辑}
}, [isLoaded]); 

三、最佳实践

  1. 拆分副作用:将不相关的副作用拆分到多个 useEffect
  2. 优先函数式更新:当更新依赖前一个状态时,使用函数式更新避免依赖:
    const [count, setCount] = useState(0);
    useEffect(() => {const timer = setInterval(() => {setCount(prev => prev + 1); // 不依赖 count}, 1000);return () => clearInterval(timer);
    }, []); 
    
  3. 性能优化:对于复杂计算,使用 useMemouseCallback 减少不必要的 effect 触发。

总结

useEffect 是管理副作用的强大工具,但需谨慎处理依赖项、避免无限循环,并合理清理资源。结合 ESLint 规则和 React 严格模式,可显著提高代码健壮性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/907926.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【DIY】通达信DIY添加扫雷宝、地图和复盘(1)

【写在前面】炒股软件有很多,电脑版我用的多的通达信,手机版用的多的是同花顺。之前还有一些其它的软件,比如A股通、短线王、wind股票、雪球等都有自己的特色。自己不喜欢一次装好多软件,所以就产生了聚合的念头。通达信通赢版可以登录多券商账号,懒得来回切换,所以选择以…

RabbitMQ进阶--TTL,死信队列,持久化,磁盘监控

一.消息的TTL机制 RabbitMQ中的TTL(Time-To-Live,存活时间)是指消息或队列的过期时间。TTL机制允许你指定消息在未被消费前可以存活的时间长度,超过这个时间后,消息将被视为“死亡”,并从队列中移除。这种机制对于控制消息的有效性和资源管理非常有用。 防止积压消息:当…

day41 基础的模块

基础模块 ad-hoc命令模式pingcommandshellcopyfilescriptcrongroupuser1.先看资料,看模块的语法 - 官网,看实例用法,语法注解 - ansible-doc -s 模块名 - 你自己的学习笔记2.每一个模块独有的参数语法,都是 ad-hoc命令模式ansible 主机组 -m 模块名 -a "模块独有的…

Java面试基础

一、Java基础语法 1.1 环境搭建与开发 1、JDK、JRE、JVM的关系和区别?(高频plus)JDK:Java Development Kit,Java开发工具包,包含了JRE和一系列Java开发工具。 JRE:Java Runtime Environment,Java程序的运行环境,包含JVM、Java核心类库等。JRE只能用来运行Java应用程序…

day41 Ansible剧本的语法

day41--ansible剧本的学习 1.剧本的主题的内容剧本就是两大部分的知识点 -ansible 模块(以及模块的参数) -yaml语法3.工作以后 维护公司的剧本 -看剧本,看懂了,维护,修改 -修改各种的参数,文件的路径,文件的名字,服务的端口名字(就是该ansible各种的参数,参数的值)2。…

Windows系统迁移用户目录

Windows系统随着使用时间的延长,系统盘空间占用会越来越大,对于一些硬盘空间有限的主机而言,C盘空间剩余就越来越少,稍不注意可以可能就被占满了,导致系统都无法启动。正好我自己的笔记本电脑也遇到了同样的问题,因此就想把C:\Users目录迁移到其他分区中。 在实践中,使用…

iphone---苹果手机传输文件

使用手机,拍了一些照片和剪辑了一些视频,但是总感觉将手机里面的图片及视频传到电脑里面和麻烦,今天试了一下用U盘传,效率还可以,但是其中也遇到了一些问题,就在这里记录下: 传输方法:插入U盘,选择图片或文件,点击【分享】选择【存储到“文件”】点击【左上角浏览】…

Python+硅基流动API实现小说转有声读物

一、注册硅基流动账号获取文本转语音api 1.注册登录硅基流动注册、登录硅基流动查看apikey查看赠送的免费额度点击文档中心2.查看文本转语音api查看文本转语音api查看api使用指南查看文本转语音api的python调用方法二、python实现文本转语音功能 1.python调用api实现文本转语音…

蓝绿部署深度解析:从理论到实践的全方位学习指南

一、蓝绿部署的基本概念 (一)定义 蓝绿部署是一种软件发布策略,通过设置两个相同的环境(“蓝色”和“绿色”),最大限度地减少停机并降低与部署新版本应用程序相关的风险。 (二)工作原理 蓝绿部署的核心思想是将应用程序的部署过程分为两个阶段:测试阶段和生产阶段。在…

Elasticsearch 高级

Elasticsearch 高级建议阅读顺序:Elasticsearch 入门 Elasticsearch 搜索 Elasticsearch 搜索高级 Elasticsearch高级(本文)1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构,比如一个用户可能有多个地址,或者一个博客文章可能有…

mysql日志写马

mysql日志写马 条件 1.全局变量general_log为ON。 mysql有两个全局变量:general_log指的是日志保存状态,值为ON/OFF,general_log_file指的是日志的保存路径。 只有当general_log为ON时,日志才会被记录进去,所以我们要先打开这个全局变量,使用命令查看全局变量状态‘ show…

滚动部署学习指南:从理论到实践,掌握关键技术和流程

一、滚动部署概述 (一)定义 滚动部署是一种逐步更新应用实例的策略,通过逐批次替换旧版本实例来完成版本升级,以减少服务中断时间并降低更新风险。 (二)应用场景 滚动部署适用于需要高可用性和低风险的软件更新场景,例如 Web 应用程序更新、移动应用后端服务更新以及云原…