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
相关产品推荐
相关产品推荐

