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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:15:06