You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React页面加载时fetch重复调用API两次是什么原因?

问题根源

这个接口被调用两次的现象不是代码逻辑bug,是React 18及以上版本开发环境的默认设计,由严格模式(Strict Mode)的重复渲染校验机制触发。

  • Create React App新建的项目默认会在入口文件src/index.js里用<React.StrictMode>包裹整个应用,开启所有严格模式校验规则
  • 开发环境下,严格模式会主动执行一次「组件挂载 -> 组件卸载 -> 组件重新挂载」的流程,用来提前排查组件里不规范的副作用写法、过期闭包、内存泄漏等问题
  • 你把fetch请求直接写在组件函数的顶层,组件每次渲染、每次重新挂载都会执行这段请求代码,所以页面加载阶段会触发两次接口调用

这个重复执行逻辑只在开发环境生效,生产环境打包部署后,组件只会正常挂载一次,接口也只会调用一次,不会影响线上运行效果。

正确处理方式

不要直接把副作用逻辑(比如接口请求、事件绑定、定时器注册)写在组件函数顶层,应该放到useEffect钩子中管理,配合空依赖数组保证仅在组件挂载时执行,同时写好清理逻辑避免内存泄漏,示例代码如下:

import { useEffect } from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  useEffect(() => {
    // 用AbortController控制请求取消,避免组件卸载后请求仍在执行
    const abortController = new AbortController();
    
    fetch('https://localhost:44386/weatherforecast', {
      signal: abortController.signal
    })
    .then(res => res.text())
    .then(data => console.log(data))
    .catch(err => {
      // 忽略主动取消请求抛出的错误
      if (err.name !== 'AbortError') console.error(err);
    });

    // 组件卸载时执行清理:取消未完成的请求
    return () => abortController.abort();
  }, []); // 空依赖数组代表仅在组件首次挂载时执行副作用

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

如果不需要严格模式的校验能力,也可以直接到src/index.js中删除根组件外层的<React.StrictMode>标签,关闭后开发环境也不会触发重复挂载,但不推荐这么做——严格模式能提前帮你发现很多潜在的代码隐患,减少线上出问题的概率。
不要为了规避开发环境的两次调用,给请求加全局锁、单例判断这类补丁,这类多余逻辑会被带到生产环境,反而造成不必要的性能开销和逻辑bug。

内容的提问来源于stack exchange,提问作者CraftyFox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:15:41