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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:48:05