React 开启 Strict Mode 后 useEffect 被执行了两次,正常吗? 极客钰曦 提问于 2026-02-24 22:45:17 阅读 20 框架 我在开发 React 应用时开启了 Strict Mode,结果发现组件里的 useEffect 在开发环境下执行了两次,导致接口被请求了两遍,这正常吗?我是不是哪里写错了? 这是我的代码: useEffect(() => { console.log('Fetching data...'); fetchData(); }, []); ReactRedux性能优化 我来解答 赞 3 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 1 条解答 ❤志诚 Lv1 这事儿我太熟了,当年我也被这个坑过好几次。Strict Mode 在开发环境里故意把 useEffect 的回调执行两次,是它故意设计的,不是你写错了。目的就一个:帮你提前发现那些「副作用没做好清理」或者「依赖没写全」的隐性 Bug。 比如你这个例子里,如果 fetchData 是个网络请求,那它确实会发两次,但注意——生产环境不会这样,只有开发环境会。所以你要是上线后发现正常了,别慌,就是这个机制在起作用。 怎么验证?你可以打包后跑 npm run build && serve -s build 看看,就一次了。 不过既然它触发了两次,说明你这副作用得认真检查下: - 有没有在 fetchData 里没做防重处理?比如加个 loading 标志,或者 abort 上一次请求 - 有没有依赖项漏写?比如 fetchData 本身是不是用 useCallback 包的?要是没包,每次 render 都是新函数,那就算你写了空数组也会重执行 - 清理函数写没写?比如请求取消、订阅取消这些,Strict Mode 会调用两次,第一次执行完会立刻再执行一次,中间夹着个清理函数 要是你就是想临时屏蔽这个双执行(比如调试阶段怕日志刷屏),可以在开发时用 process.env.NODE_ENV === 'development' 包一层,但不推荐长期这么干,毕竟漏掉的问题迟早要还。 我以前在主题里加过一个全局的 console.warn 拦截,专门打印 useEffect 重复执行的 stack trace,后来发现真查出好几次没清理的订阅,血亏。所以这事儿别当成 bug 解决,当成个提醒机制就好。 回复 点赞 2 2026-02-24 23:01 加载更多 相关推荐 1 回答 4 浏览 React Strict Mode 下 useEffect 为什么会执行两次? 我在开发时开启了 React 的 Strict Mode,结果发现 useEffect 里的逻辑执行了两次,明明只渲染了一次组件。这是正常现象吗?会不会影响生产环境? 我试过把依赖数组清空,也试过移除... 慕容梓晨 框架 2026-03-02 17:50:20 1 回答 63 浏览 React Strict Mode为什么导致useEffect两次执行?代码没问题却报错 我在React组件里用Strict Mode包裹App时,发现useEffect里的API请求执行了两次,控制台还报错说useState未定义。但移除Strict Mode后就正常了,这是为什么? 比... ♫慧慧 框架 2026-02-19 10:09:50 1 回答 16 浏览 React 开启 Strict Mode 后 useEffect 为啥执行了两次? 我在开发 React 应用时,发现只要在根组件包了 StrictMode,里面的 useEffect 就会执行两次,明明只写了一次逻辑。这是 bug 吗?还是我哪里理解错了? 比如下面这段代码,在控制... 司卿 框架 2026-02-26 16:40:21 2 回答 37 浏览 React中setTimeout和useEffect的执行顺序为什么不符合预期? 我在用React写一个计数器组件,点击按钮后先调用setTimeout再更新状态,但发现useEffect里的console.log总是先于setTimeout里的输出。明明setTimeout在代码... 技术巧梅 前端 2026-02-17 22:26:26 1 回答 54 浏览 Figma Dev Mode导出的组件样式在React中不生效怎么办? 我用Figma Dev Mode导出的按钮组件CSS,在React项目里直接复制粘贴后样式完全没效果。按钮显示成默认的方形,颜色也没变化。之前按照文档配置了正确的类名,但检查元素发现CSS变量好像没被... Mr-景叶 工具 2026-02-16 04:41:37 2 回答 29 浏览 React中使用strict-dynamic后动态内联样式还是被CSP拦截怎么办? 最近给项目加CSP防护时遇到怪事,按照文档在nonce策略里加了'strict-dynamic',但React组件里的动态内联样式还是被拦截。明明设置了nonce和函数生成样式啊... 代码大概是这样... Good“秀玲 安全 2026-01-26 23:09:29 0 回答 1 浏览 useEffect 为什么在组件首次渲染时就执行了? 我刚学 React,看到 useEffect 默认会在组件挂载后执行一次,但我不太理解为什么它不等依赖变化才运行。比如我在 Vue 里用 watch 是不会一进来就触发的,但在 React 里写了个空... 码农翌耀 框架 2026-03-02 22:19:21 2 回答 52 浏览 React Error Boundaries为什么在函数组件中无法捕获子组件错误? 我在React项目中用类组件实现了Error Boundary,但今天改用函数组件+useEffect模拟时,子组件报错后页面还是直接崩溃了。之前按照文档写了 componentDidCatch 方法... Des.书圻 框架 2026-02-06 10:03:16 1 回答 76 浏览 React组件用useEffect定时器内存持续增长怎么办? 我在开发一个实时数据展示组件时用到了useEffect里的setInterval,但组件卸载后内存一直没释放。虽然加了cleanup函数,但内存分析工具显示heap还在持续增长,这是什么问题啊? 代码... 小令敏 优化 2026-02-05 11:00:32 1 回答 72 浏览 React组件测试时为什么mock的API没有被调用? 我在用Jest+React Testing Library测试一个组件时遇到了问题。组件里用useEffect调用了外部API,我按教程写了mock但测试总是失败: // userApi.js exp... 司徒惠泽 框架 2026-01-29 16:24:30
比如你这个例子里,如果
fetchData是个网络请求,那它确实会发两次,但注意——生产环境不会这样,只有开发环境会。所以你要是上线后发现正常了,别慌,就是这个机制在起作用。怎么验证?你可以打包后跑
npm run build && serve -s build看看,就一次了。不过既然它触发了两次,说明你这副作用得认真检查下:
- 有没有在
fetchData里没做防重处理?比如加个 loading 标志,或者 abort 上一次请求- 有没有依赖项漏写?比如
fetchData本身是不是用useCallback包的?要是没包,每次 render 都是新函数,那就算你写了空数组也会重执行- 清理函数写没写?比如请求取消、订阅取消这些,Strict Mode 会调用两次,第一次执行完会立刻再执行一次,中间夹着个清理函数
要是你就是想临时屏蔽这个双执行(比如调试阶段怕日志刷屏),可以在开发时用
process.env.NODE_ENV === 'development'包一层,但不推荐长期这么干,毕竟漏掉的问题迟早要还。我以前在主题里加过一个全局的
console.warn拦截,专门打印 useEffect 重复执行的 stack trace,后来发现真查出好几次没清理的订阅,血亏。所以这事儿别当成 bug 解决,当成个提醒机制就好。