大家好,我是展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
- 前言
- useEffect 的本质是什么?
- useEffect 滥用的典型场景
- 1. 用 useEffect 做派生状态
- 2. useEffect 控制渲染逻辑
- 3. 复杂组件里写“多条 effect”
- 为什么大部分 useEffect 可以删掉
- 原因 1:effect 被用作“状态计算”
- 原因 2:effect 被用作“条件渲染”
- 原因 3:effect 被用作“组合逻辑”
- 判断一个 useEffect 是否必须
- 真实案例拆解
- 原始写法
- 滥用示例
- 优化 useEffect 的策略
- 策略 1:计算 vs 副作用分离
- 策略 2:把副作用下沉到自定义 Hook
- 策略 3:effect 只做三件事
- 总结
前言
如果你写过 React 或 React Native,一定有这种感受:
- 页面里 useEffect 太多,刷新一次就好像在跑马拉松
- eslint 一堆依赖提示,你直接关掉就完事
- 改个状态,结果一串 effect 被触发,页面像爆炸一样
那么问题来了:
大部分 useEffect,真的用对了吗?
没错——在真实项目里,我发现90% 的 useEffect 都可以删掉。
今天就来聊聊为什么,删掉后还能让项目更稳、更易维护。
useEffect 的本质是什么?
一句话总结:
useEffect = 当某些值变化时,要执行一件副作用操作。
副作用(side effect)指的是:
- 网络请求
- 订阅 / 监听
- 与外部系统交互(例如导航、Alert、定时器)
注意:计算、派生状态、渲染逻辑,都不算副作用。
useEffect 滥用的典型场景
1. 用 useEffect 做派生状态
const[total,setTotal]=useState(0)useEffect(()=>{setTotal(price*count)},[price,count])问题:
- total 可以直接计算,不需要放 state
- useEffect 成了“状态中转站”,增加维护成本
改进:
consttotal=price*count2. useEffect 控制渲染逻辑
useEffect(()=>{if(user)setShow(true)},[user])其实完全可以:
constshow=!!usereffect 没有副作用,只是为了“转换数据”,完全可以删掉。
3. 复杂组件里写“多条 effect”
useEffect(()=>{fetchA()},[a])useEffect(()=>{fetchB()},[b])useEffect(()=>{doC()},[c])问题:
- 逻辑分散,难调试
- 很多 effect 可以合并或者直接放到 hook 里处理
- page 层成为副作用的集合体
为什么大部分 useEffect 可以删掉
总结下来,有三个核心原因:
原因 1:effect 被用作“状态计算”
很多人写:
useEffect(()=>{setFiltered(list.filter(item=>item.active))},[list])本质上这是计算,不是副作用
可以直接用:
constfiltered=list.filter(item=>item.active)原因 2:effect 被用作“条件渲染”
useEffect(()=>{setVisible(flag)},[flag])这根本不需要 effect
直接:
constvisible=flag原因 3:effect 被用作“组合逻辑”
useEffect(()=>{if(a&&b)doSomething()},[a,b])可以考虑:
- 把逻辑下沉到 hook
- 或者用 useMemo / useCallback 组合
判断一个 useEffect 是否必须
问自己三个问题:
- 这个 effect 有副作用吗?
- 它在做计算还是同步状态吗?
- 它会和外部系统交互吗?
如果答案都是否定的,删掉它,改用计算或 memo 化。
真实案例拆解
原始写法
const[loading,setLoading]=useState(false)const[list,setList]=useState([])useEffect(()=>{setLoading(true)fetchData(params).then(res=>{setList(res)setLoading(false)})},[params])这里的 useEffect 是必须的,因为 fetchData 属于副作用。
滥用示例
const[visible,setVisible]=useState(false)useEffect(()=>{setVisible(user!==null)},[user])可以改成:
constvisible=user!==null效果一样,但删掉一个 effect,页面更轻量。
优化 useEffect 的策略
策略 1:计算 vs 副作用分离
- 所有派生状态、计算,尽量用变量或 useMemo
策略 2:把副作用下沉到自定义 Hook
- fetch / subscribe / navigation 都写在 hook 里
- 页面只组装,不写 effect
策略 3:effect 只做三件事
- 网络请求
- 外部系统交互
- 订阅 / 监听
其他一律不要。
总结
- 90% 的 useEffect 可以删掉,因为它们承担了不该它承担的逻辑
- effect 是副作用,不是状态计算工具
- 副作用要集中、可预测、可组合,乱写只会让项目失控
当你开始用“副作用视角”审查 useEffect,你会发现:
- 页面逻辑更清晰
- eslint 不再可怕
- 性能更稳,bug 更少