React组件调用YouTube Data API无限请求致配额耗尽求助
问题:React组件无限调用YouTube API导致配额耗尽
我是React新手,正在开发类似YouTube播放器的组件,要在桌面右侧展示YouTube播放列表的所有视频。朋友给的代码初期运行正常,但几分钟就耗尽了Google API每日配额,右侧播放列表变空白,控制台出现大量GET请求错误。请找出代码中无限发送GET请求的原因。
问题代码
import axios from 'axios'; import React from 'react' import { useState } from "react"; export default function PlayerItem() { const [data, setData] = useState([]); const details = [] async function gettingData() { await axios.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLu0W_9lII9aiL0kysYlfSOUgY5rNlOhUd&key=[myKey]').then(res => { setData(res.data.items) }); } gettingData(); data.forEach(element => { details.push(element.snippet.title) }); // console.log(details); return ( <> {details.map((title, index) => ( <div className="pl-item" key={index}> <strong>Video {index + 1}</strong> : {title}. </div> ) )} </> ) }

问题原因
核心问题是直接在组件函数体内调用了gettingData(),这会触发无限重渲染循环:
- 组件每次渲染时,都会执行
gettingData(),发送一次API请求 - 请求完成后调用
setData()更新状态,状态变更会触发组件重新渲染 - 重新渲染时又会再次调用
gettingData(),循环往复,导致短时间内发送大量API请求,直接耗尽Google API的每日配额
解决方案
方法1:使用useEffect钩子(推荐)
把API请求放在useEffect钩子中,设置空依赖数组,确保请求只在组件挂载时执行一次:
import axios from 'axios'; import React, { useState, useEffect } from 'react'; export default function PlayerItem() { const [data, setData] = useState([]); async function gettingData() { try { const res = await axios.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLu0W_9lII9aiL0kysYlfSOUgY5rNlOhUd&key=[myKey]'); setData(res.data.items); } catch (err) { console.error('获取播放列表数据失败:', err); } } // 仅在组件首次挂载时执行请求 useEffect(() => { gettingData(); }, []); return ( <> {data.map((item, index) => ( <div className="pl-item" key={item.id || index}> <strong>Video {index + 1}</strong> : {item.snippet.title}. </div> ))} </> ) }
额外优化点:
- 直接用
data.map渲染列表,不需要额外的details中转数组 - 添加
try/catch捕获请求错误,避免请求失败导致组件异常 - 优先使用视频的
id作为key(而非索引),提升列表渲染性能
方法2:条件判断触发请求(不推荐)
如果暂时不想用useEffect,可以通过判断data为空时才发送请求,但这种方式不如useEffect稳定:
// ...其他代码不变 if (data.length === 0) { gettingData(); } // ...其他代码不变
内容的提问来源于stack exchange,提问作者Satyam Nagar
相关产品推荐
相关产品推荐

