你有没有发现一个现象只要写 React就离不开useEffect数据变了 → 加 useEffect不知道逻辑放哪 → 塞 useEffect页面不更新 → 再加一层 useEffect写到最后组件里一半代码都是 useEffect无限循环、重复请求、莫名其妙重渲染、闭包陷阱满天飞改 Bug 比写功能还累这篇文章只讲一件事useEffect 到底是什么以及它为什么被 90% 的人用错先讲背景useEffect 到底是干嘛的早期 React 组件有一堆生命周期componentDidMount、componentDidUpdate、componentWillUnmount…逻辑散得到处都是维护巨痛苦。Hook 出来后React 想解决一个问题把“跟渲染无关、跟外部交互”的逻辑统一收拢。于是有了useEffect。它的定位非常清晰处理副作用Side Effect。什么是副作用就是跳出 React 渲染逻辑、去跟外部打交道的操作请求 API 接口操作真实 DOM比如聚焦第三方库定时器、延时局事件监听resize、keydown本地存储、document.title同步外部系统日志、埋点一句话总结只有需要和“外部世界”同步时才需要 useEffect。致命误解你把它当成了 “监听器”这是 React 新手最大的误区。你以为它是监听某个变量变化然后执行逻辑。但 React 的核心模型是UI f (state)纯函数请死死记住这句话useEffect 不是 “监听变量变化”而是 “处理副作用”。一旦滥用React 内部发生了什么你写了一个逻辑React 执行了一条死循环render (渲染) → effect (执行副作用) → setState (更新状态) → render (再次渲染) → effect …你以为只写了几行代码其实你在 React 里开了一条高速公路车多了自然堵车。滥用 useEffect 的三大灾难多余渲染暴增性能杀手一次逻辑触发多次渲染页面卡顿、掉帧。依赖链混乱Bug 温床依赖数组稍微不严谨就陷入无限循环或者闭包陷阱数据对不上。逻辑碎片化维护灾难一个功能拆碎在多个不同的 useEffect 里逻辑碎片化谁敢动典型灾难链A 改 B → B 改 C → C 再改 A你以为你在写逻辑其实你在堆 Bug。这 4 种场景绝对别用 useEffect1. 计算状态 → 直接算别存状态// ❌ 错误多此一举引发重复渲染const[a,setA]useState(1)const[b,setB]useState(0)useEffect((){setB(a*2)},[a])// ✅ 正确直接计算consta1constba*2// 直接计算能通过现有状态直接算出来的就不要单独存状态避免多余的渲染和逻辑。2. 交互逻辑 → 写在事件处理函数里不是 useEffect// ❌ 错误为了弹个提示监听整个countuseEffect((){if(count10)alert(够了)},[count])// ✅ 正确点击时直接判断consthandleClick(){constnewCountcount1setCount(newCount)if(newCount10)alert(够了)}用户主动触发的行为不属于副作用同步理应写在对应的事件处理函数中。3. 初始化数据 → useState 初始值就能搞定// ❌ 错误多一次renderconst[user,setUser]useState(null)useEffect((){setUser(currentUser)},[])// ✅ 正确一步到位直接初始化const[user]useState(currentUser)4. Props 同步 → 直接用 props不要本地状态effect// ❌ 错误典型反模式数据来源不单一useEffect((){setValue(props.value)},[props.value])// ✅ 直接用 propsconst{value}props useEffect 的唯一合法使用场景只记5 种合法场景多一个都不用接口请求记得必须带 AbortController 清理定时器 / 延时必须 clear手动操作 DOM全局事件监听addEventListener 必须 remove同步外部系统localStorage、title、埋点除此之外能不用就不用。结尾很多人以为问题在 useEffect其实问题在这里你有没有把组件当成“纯函数”通俗来讲React 组件本该是纯函数固定的 Props 和 State就输出固定的 UI不掺杂多余的副作用。滥用 useEffect 就是强行打破这个规则在渲染中乱加状态修改、异步逻辑才引发各种 Bug 和性能问题。你认为呢Vue 的 Watch 是不是也是这个道理欢迎在评论区一起讨论
useEffect 到底是什么?以及它为什么被 90% 的人用错?
发布时间:2026/5/27 18:36:26
你有没有发现一个现象只要写 React就离不开useEffect数据变了 → 加 useEffect不知道逻辑放哪 → 塞 useEffect页面不更新 → 再加一层 useEffect写到最后组件里一半代码都是 useEffect无限循环、重复请求、莫名其妙重渲染、闭包陷阱满天飞改 Bug 比写功能还累这篇文章只讲一件事useEffect 到底是什么以及它为什么被 90% 的人用错先讲背景useEffect 到底是干嘛的早期 React 组件有一堆生命周期componentDidMount、componentDidUpdate、componentWillUnmount…逻辑散得到处都是维护巨痛苦。Hook 出来后React 想解决一个问题把“跟渲染无关、跟外部交互”的逻辑统一收拢。于是有了useEffect。它的定位非常清晰处理副作用Side Effect。什么是副作用就是跳出 React 渲染逻辑、去跟外部打交道的操作请求 API 接口操作真实 DOM比如聚焦第三方库定时器、延时局事件监听resize、keydown本地存储、document.title同步外部系统日志、埋点一句话总结只有需要和“外部世界”同步时才需要 useEffect。致命误解你把它当成了 “监听器”这是 React 新手最大的误区。你以为它是监听某个变量变化然后执行逻辑。但 React 的核心模型是UI f (state)纯函数请死死记住这句话useEffect 不是 “监听变量变化”而是 “处理副作用”。一旦滥用React 内部发生了什么你写了一个逻辑React 执行了一条死循环render (渲染) → effect (执行副作用) → setState (更新状态) → render (再次渲染) → effect …你以为只写了几行代码其实你在 React 里开了一条高速公路车多了自然堵车。滥用 useEffect 的三大灾难多余渲染暴增性能杀手一次逻辑触发多次渲染页面卡顿、掉帧。依赖链混乱Bug 温床依赖数组稍微不严谨就陷入无限循环或者闭包陷阱数据对不上。逻辑碎片化维护灾难一个功能拆碎在多个不同的 useEffect 里逻辑碎片化谁敢动典型灾难链A 改 B → B 改 C → C 再改 A你以为你在写逻辑其实你在堆 Bug。这 4 种场景绝对别用 useEffect1. 计算状态 → 直接算别存状态// ❌ 错误多此一举引发重复渲染const[a,setA]useState(1)const[b,setB]useState(0)useEffect((){setB(a*2)},[a])// ✅ 正确直接计算consta1constba*2// 直接计算能通过现有状态直接算出来的就不要单独存状态避免多余的渲染和逻辑。2. 交互逻辑 → 写在事件处理函数里不是 useEffect// ❌ 错误为了弹个提示监听整个countuseEffect((){if(count10)alert(够了)},[count])// ✅ 正确点击时直接判断consthandleClick(){constnewCountcount1setCount(newCount)if(newCount10)alert(够了)}用户主动触发的行为不属于副作用同步理应写在对应的事件处理函数中。3. 初始化数据 → useState 初始值就能搞定// ❌ 错误多一次renderconst[user,setUser]useState(null)useEffect((){setUser(currentUser)},[])// ✅ 正确一步到位直接初始化const[user]useState(currentUser)4. Props 同步 → 直接用 props不要本地状态effect// ❌ 错误典型反模式数据来源不单一useEffect((){setValue(props.value)},[props.value])// ✅ 直接用 propsconst{value}props useEffect 的唯一合法使用场景只记5 种合法场景多一个都不用接口请求记得必须带 AbortController 清理定时器 / 延时必须 clear手动操作 DOM全局事件监听addEventListener 必须 remove同步外部系统localStorage、title、埋点除此之外能不用就不用。结尾很多人以为问题在 useEffect其实问题在这里你有没有把组件当成“纯函数”通俗来讲React 组件本该是纯函数固定的 Props 和 State就输出固定的 UI不掺杂多余的副作用。滥用 useEffect 就是强行打破这个规则在渲染中乱加状态修改、异步逻辑才引发各种 Bug 和性能问题。你认为呢Vue 的 Watch 是不是也是这个道理欢迎在评论区一起讨论