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

React中fetch仅调用一次却发起多次网络请求问题求解

问题原因

你遇到的是React 18+版本默认开启的严格模式(Strict Mode)带来的开发环境特性,和业务逻辑本身无关。

通过create-react-app创建的新项目,默认会在入口文件index.js中把根组件包裹在<React.StrictMode>标签内,这个配置在开发环境下会故意执行两次组件渲染逻辑,用来提前暴露代码中隐藏的副作用问题。
React 18同时新增了控制台日志消噪功能,第二次渲染产生的console.log会被默认置灰隐藏,你观察到的「App()函数和logStuff()仅调用一次」是日志被过滤后的错觉,实际上两个函数都执行了两次,所以才会触发两次fetch请求和两次成功回调日志。

验证方式

打开项目的src/index.js文件,删除外层的<React.StrictMode>标签,重启服务后即可看到请求变为1次,符合预期。需要注意的是严格模式仅在开发环境生效,生产环境打包后不会出现重复执行的问题,不会影响线上使用。

最佳实践优化

你现在直接在组件return语句中执行包含fetch的副作用函数,不符合React的设计规范。所有副作用操作都应该放到useEffect钩子中执行,参考写法如下:

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

function App() {
  console.log("###? App()");

  const logStuff = () => {
    console.log("###? Logging stuff")
    fetch("https://httpbin.org/post", {
      method: 'POST',
      body: JSON.stringify({error: "hello", message: "there"}),
    })
      .then(() => console.log('###? useLog() response'))
      .catch((error) => {
        console.error('###? Failed to send log with error: ' + error);
      });
  }

  // 空依赖数组代表仅在组件挂载时执行一次
  useEffect(() => {
    logStuff();
  }, []);

  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;

如果需要在严格模式开发环境下也完全避免重复执行,可以加ref标记做判断:

import { useEffect, useRef } from 'react';

// 组件内逻辑
const isExecuted = useRef(false);
useEffect(() => {
  if (!isExecuted.current) {
    logStuff();
    isExecuted.current = true;
  }
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:24:02