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

React中YouTube API数据无法存入useState变量的排查方案

React中调用YouTube API数据无法存入useState导致组件不渲染的排查与修复

问题描述

调用YouTube API成功拉取数据后,数据无法正常存入useState变量,依赖该数据的VideoCard组件无法渲染。

提供的代码

import React, { useEffect, useState } from "react";
import { YOUTUBE_VIDEOS_API } from "../utils/constants";
import VideoCard from "./VideoCards";

const VideoContainer = () => {
  const [videos, setVideos] = useState([]);

  useEffect(() => {
    getVideos();
  }, []);

  const getVideos = async () => {
    try {
      const data = await fetch(YOUTUBE_VIDEOS_API);
      const json = await data.json();

      setVideos([...videos, ...json?.items]);
      console.log(json);
    } catch (e) {
      console.error(e);
    }
  };

  return (
    <div className="m-4 flex flex-wrap">
      {videos.map((card, index) => {
        <VideoCard key={index} card={card} />;
      })}
    </div>
  );
};

export default VideoContainer;

API返回的JSON结构

{
  "kind":  "youtube#videoListResponse",
  "etag": "fQlUo5S4JJ9QA_SUhvAXezB2SHI",
  "items": [{.....},{.....},{.....}],
  "nextPageToken": "CAUQAA"
}

排查与修复步骤

1. 修复组件渲染的直接问题

你的map循环里没有返回VideoCard组件,React无法识别要渲染的元素。两种修复方式:

  • 显式添加return:
    videos.map((card, index) => {
      return <VideoCard key={index} card={card} />;
    })
    
  • 用箭头函数隐式返回(去掉大括号):
    videos.map((card, index) => 
      <VideoCard key={index} card={card} />
    )
    

2. 修正useState更新的闭包陷阱

当前用setVideos([...videos, ...json?.items])依赖的是初始渲染时的空数组闭包,后续分页加载会丢失之前的状态。改用函数式更新,确保每次拿到最新状态:

setVideos(prevVideos => [...prevVideos, ...json?.items]);

3. 验证状态是否正确更新

React状态更新是异步的,直接在setVideos后打印videos会得到旧值。可以通过监听状态变化的useEffect来验证:

useEffect(() => {
  console.log('videos状态已更新:', videos);
}, [videos]);

4. 确保API返回的items有效

加判断避免json?.items不是数组的情况:

if (json?.items && Array.isArray(json.items)) {
  setVideos(prev => [...prev, ...json.items]);
} else {
  console.warn('API返回的items不是有效数组');
}

最终修复后的完整代码

import React, { useEffect, useState } from "react";
import { YOUTUBE_VIDEOS_API } from "../utils/constants";
import VideoCard from "./VideoCards";

const VideoContainer = () => {
  const [videos, setVideos] = useState([]);

  useEffect(() => {
    getVideos();
  }, []);

  // 监听状态变化,验证数据是否存入
  useEffect(() => {
    console.log('当前videos列表:', videos);
  }, [videos]);

  const getVideos = async () => {
    try {
      const data = await fetch(YOUTUBE_VIDEOS_API);
      const json = await data.json();

      if (json?.items && Array.isArray(json.items)) {
        // 函数式更新获取最新状态
        setVideos(prevVideos => [...prevVideos, ...json.items]);
      } else {
        console.warn('未获取到有效视频数据');
      }
    } catch (e) {
      console.error('获取视频数据失败:', e);
    }
  };

  return (
    <div className="m-4 flex flex-wrap">
      {/* 隐式返回组件,确保渲染 */}
      {videos.map((card, index) => 
        <VideoCard key={index} card={card} />
      )}
    </div>
  );
};

export default VideoContainer;

内容的提问来源于stack exchange,提问作者Vinod

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:58:31