Vite+React项目中useEffect触发429请求过多错误的解决方法
解决React useEffect空依赖仍多次请求导致429错误的问题
为什么空依赖数组还会触发多次请求?
你遇到的情况是Vite开发环境下React Strict Mode导致的。Strict Mode在开发阶段会刻意重复执行useEffect、组件挂载/卸载等生命周期逻辑,目的是帮你提前检测潜在的bug(比如未清理的订阅、内存泄漏)。这种重复执行只在开发环境存在,生产环境不会出现。
解决方案
方案1:开发环境临时关闭Strict Mode(不推荐长期使用)
找到项目入口文件(通常是src/main.jsx或src/main.tsx),移除包裹根组件的<React.StrictMode>标签:
// 修改前 import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <App /> </React.StrictMode>, ) // 修改后 import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' ReactDOM.createRoot(document.getElementById('root')).render( <App />, )
去掉后useEffect在开发环境只会执行一次,但不建议长期关闭Strict Mode,它能帮你提前发现很多潜在问题。
方案2:用AbortController取消重复请求(推荐)
使用AbortController可以在Strict Mode重复执行useEffect时,取消上一次未完成的请求,避免无效请求触发429错误,同时还能防止组件卸载时的内存泄漏:
import React, { useState, useEffect } from 'react' function QuizMain() { const [data, setData] = useState(null) useEffect(() => { const abortController = new AbortController() const { signal } = abortController fetch("https://opentdb.com/api.php?amount=5&category=9&difficulty=medium&type=multiple", { signal }) .then(res => { if (!res.ok) throw new Error(`HTTP错误:${res.status}`) return res.json() }) .then(fetchedData => { setData(fetchedData) console.log(fetchedData) }) .catch(err => { // 忽略取消请求的错误 if (err.name !== 'AbortError') { console.error('请求失败:', err) } }) // 组件卸载或useEffect重新执行时取消请求 return () => abortController.abort() }, []) return ( <div> {data ? ( <div>请求成功:{JSON.stringify(data)}</div> ) : ( <div>加载中...</div> )} </div> ) } export default QuizMain
方案3:用状态标记避免重复请求
通过一个状态变量标记是否已经完成请求,第二次执行useEffect时直接跳过:
import React, { useState, useEffect } from 'react' function QuizMain() { const [data, setData] = useState(null) const [hasFetched, setHasFetched] = useState(false) useEffect(() => { // 已经请求过就直接返回 if (hasFetched) return fetch("https://opentdb.com/api.php?amount=5&category=9&difficulty=medium&type=multiple") .then(res => res.json()) .then(fetchedData => { setData(fetchedData) setHasFetched(true) console.log(fetchedData) }) }, [hasFetched]) return ( <div> {data ? ( <div>请求成功:{JSON.stringify(data)}</div> ) : ( <div>加载中...</div> )} </div> ) } export default QuizMain
总结
- 开发环境的Strict Mode是多次请求的根源,生产环境不会有这个问题
- 推荐使用
AbortController方案,既解决重复请求问题,又符合React最佳实践 - 如果只是开发时临时调试,可以暂时关闭Strict Mode,但记得开发完成后恢复
内容的提问来源于stack exchange,提问作者Samiul Islam
相关产品推荐
相关产品推荐

