为什么我讨厌 React 的 useEffect?一篇让无数开发者共鸣的爆款吐槽!

3,122 阅读3分钟

在前端开发圈,React 的 useEffect 钩子几乎成了“进阶开发者”的标配。但你有没有觉得,明明是为了解决“副作用”管理问题而生的 useEffect,反而让代码变得更难维护、更容易踩坑?今天,就来聊聊 React useEffect 到底哪里让人抓狂,以及为什么越来越多开发者怀念起了老派的 Class 组件。

一、useEffect:初衷很美好,现实很骨感

React Hooks 诞生之初,官方给出的愿景是“让函数组件也能拥有状态和生命周期能力”。useEffect 作为副作用管理的核心工具,看起来确实很优雅:

useEffect(() => {
  // 这里写副作用逻辑,比如请求数据、监听事件等
  return () => {
    // 清理副作用
  };
}, [依赖项]);

但实际开发中,useEffect 会带来这些问题:

  • • 依赖数组容易写错,导致无限循环或副作用失效
  • • 副作用逻辑混杂在一起,代码可读性变差
  • • 清理副作用的 return 语法不直观,容易遗漏

二、useEffect 的常见“地狱场景”

1. 依赖项难以管理

比如你需要监听 props、state 的变化,稍不留神就会遗漏某个依赖,或者加多了导致副作用反复执行:

useEffect(() => {
  fetchData();
}, [userId, isLoading]); // 依赖项多了,脑袋疼

2. 多个副作用串在一起

同一个组件里,有请求、事件监听、定时器……全塞进 useEffect,维护起来像解谜游戏。

3. 清理副作用容易忘

比如 window 事件解绑、定时器销毁,return 没写好,内存泄漏分分钟找上门。

三、Class 组件的“生命周期”其实更清晰

不少老开发者发现,Class 组件虽然啰嗦,但生命周期方法(componentDidMount、componentDidUpdate、componentWillUnmount)分工明确,副作用逻辑一目了然:

componentDidMount() {
  // 初始化副作用
}
componentDidUpdate(prevProps) {
  // 根据 props 变化处理副作用
}
componentWillUnmount() {
  // 清理副作用
}

对比之下,useEffect 把所有副作用揉在一起,初学者和团队协作时更容易踩坑。

四、React 社区的新趋势:用自定义 Hook 或第三方库简化 useEffect

  • • 自定义 Hook:把复杂副作用封装起来,减少重复代码
  • • Zustand、Jotai 等状态管理库:弱化 useEffect 的存在感
  • • React 18 的 useSyncExternalStore、useEvent 等新 API,尝试让副作用更结构化

五、写在最后:用 or 不用 useEffect,关键看场景

不是说 useEffect 一无是处。对于简单的副作用,比如页面加载数据、简单的事件监听,它还是很好用的。但只要业务复杂一点,建议:

  • • 拆分副作用,减少 useEffect 的“胖钩子”
  • • 多用自定义 Hook,复用逻辑
  • • 必要时考虑回归 Class 组件,或者用第三方库简化副作用管理

你有被 useEffect“坑”过吗?欢迎在评论区讲讲你的血泪史!

关注“梦兽编程”微信公众号,解锁更多前端干货与爆款技术文章!


让我们一起用更少的代码,写出更高质量、更易维护的 React 应用吧!