React 开启 Strict Mode 后 useEffect 被执行了两次,正常吗?

极客钰曦 阅读 20

我在开发 React 应用时开启了 Strict Mode,结果发现组件里的 useEffect 在开发环境下执行了两次,导致接口被请求了两遍,这正常吗?我是不是哪里写错了?

这是我的代码:

useEffect(() => {
  console.log('Fetching data...');
  fetchData();
}, []);
我来解答 赞 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