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

React中useEffect调用fetch函数重复发送请求问题求助

解决React中useEffect空依赖仍多次发送请求的问题

可能的原因及对应解决方案

1. React StrictMode 开发环境的双重执行机制

React的StrictMode在开发模式下,会刻意两次执行副作用函数(包括useEffect、状态初始化函数等),目的是检测潜在的副作用问题(比如未清理的定时器、重复订阅),生产环境下不会出现该行为。

验证方式:查看项目入口文件(如index.js),如果组件被<React.StrictMode>包裹,移除后在开发环境测试,请求会变为一次。若为此原因,属于正常开发环境校验逻辑,无需修改代码,生产环境会自动恢复正常。

2. 组件被重复挂载

若组件因父组件逻辑触发频繁卸载/重新挂载(比如父组件key值频繁变化、条件渲染反复切换),会导致useEffect在每次挂载时都执行一次。

解决:检查父组件渲染逻辑,避免不必要的组件生命周期触发,比如确保key值稳定、优化条件渲染的触发条件。

3. 函数引用不稳定导致的隐式依赖问题

fetchFunction定义在组件内部,每次组件渲染时都会重新创建函数实例。虽然useEffect依赖数组为空,但函数内部用到的状态更新函数(如setIsLoaded),若函数引用不稳定,可能引发意外的重复执行。可通过useCallback稳定函数引用:

import { useEffect, useCallback } from 'react';

// 用useCallback稳定函数引用
const fetchFunction = useCallback(() => {
  console.log("请求触发");
  axios.get(
    "someAPI",
    {
      headers: {
        "Authorization" : localStorage.getItem("token")
      },
      credentials: 'include',
    }
  )
    // axios会自动解析JSON,无需调用res.json()
    .then(
      (result) => {
        console.log(result);
        setIsLoaded(true);
        setTableData(result);
      },
      (error) => {
        setIsLoaded(true);
        setError(error);
      }
    )
}, [setIsLoaded, setTableData]); // 状态更新函数可加入依赖,它们是稳定的

useEffect(() => {
  fetchFunction();
}, [fetchFunction]) // 依赖稳定的fetchFunction

4. 添加请求防重复标志位

若上述方法无效,可通过useRef记录请求状态,强制只执行一次:

import { useEffect, useRef } from 'react';

useEffect(() => {
  const hasFetched = useRef(false);
  if (!hasFetched.current) {
    hasFetched.current = true;
    fetchFunction();
  }
}, [])

const fetchFunction =() => {
  console.log("请求触发");
  axios.get(
    "someAPI",
    {
      headers: {
        "Authorization" : localStorage.getItem("token")
      },
      credentials: 'include',
    }
  )
    .then(
      (result) => {
        console.log(result);
        setIsLoaded(true);
        setTableData(result);
      },
      (error) => {
        setIsLoaded(true);
        setError(error);
      }
    )
}

额外注意点

代码中axios.get后调用res.json()是多余的,axios会自动将响应体解析为JSON对象,直接使用result即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:57:26