首页 > 解决方案 > ReactJS(初学者)使用 Youtube API - 返回的对象不允许我访问 VideoId 属性

问题描述

我是 React 初学者,所以请放轻松。

我现在正在制作一个非常基本的应用程序,稍后我将进行扩展..

现在我只是想让 React 从 Youtube 中提取一个带有频道数据的 JSON 对象,存储返回的视频列表(我猜是状态?),然后提取视频 ID,以便我可以将它们放入一个对象中并将它们随机化以供以后播放。

我的代码可以正常提取数据,但目前我似乎无法访问每个视频 ID 的“videoId”属性......我一辈子都做不到,明白为什么视频 ID 对象可以访问,但不是它们的属性在..

似乎 YouTube API 正在返回一个对象数组..所以我认为我应该能够做到这一点:

视频[0].id.videoId

但这给出了错误...但是视频[0] .id 似乎有效,所以我迷路了..

我究竟做错了什么?我使用状态错误吗?我访问对象属性是否错误?

有关示例中的控制台日志,请参见下文:

import React, { Component } from "react";
import "./App.css";
import YouTube from "react-youtube";

class App extends Component {
  constructor(props) {
    super(props);
    console.log(">> [App.js] Inside Constructor", props);
    this.state = {
      videos: {}
    };
  }

  componentDidMount() {
    var that = this;
    var API_key = "MY API KEY IS HERE (working) ";
    var channelID = "UCs3o4RhBiP2wcwqkZR2QVLw";
    var maxResults = 10;
    var url =
      "https://www.googleapis.com/youtube/v3/search?key=" +
      API_key +
      "&channelId=" +
      channelID +
      "&part=snippet,id&order=date&maxResults=" +
      maxResults;

    fetch(url)
      .then(function(response) {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then(function(data) {
        that.setState({ videos: data.items });
        console.log(">> data items: ", data.items);
      });
  }

  render() {
    const opts = {
      height: "390",
      width: "640",
      playerVars: {
        // https://developers.google.com/youtube/player_parameters
        autoplay: 1
      }
    };

    console.log(">> states = ", JSON.stringify(this.state.videos[0]));
    //logs :
    // >> states =  {"kind":"youtube#searchResult","etag":"\"XI7nbFXulYBIpL0ayR_gDh3eu1k/z_ggxomb8RCC1cd6Bx8IrkCUHxA\"","id":{"kind":"youtube#video","videoId":"IoId8_4mvT4"},"snippet":{"publishedAt":"2017-07-18T19:12:33.000Z","channelId":"UCs3o4RhBiP2wcwqkZR2QVLw","title":"WATCH in 360 - CP24 tours Toronto Island. July 18 2017","description":"Subscribe to CP24 to watch more videos: https://www.youtube.com/channel/UCs3o4RhBiP2wcwqkZR2QVLw Connect with CP24: For the latest news visit: ...","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/IoId8_4mvT4/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/IoId8_4mvT4/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/IoId8_4mvT4/hqdefault.jpg","width":480,"height":360}},"channelTitle":"CP24","liveBroadcastContent":"none"}}

    console.log(">> states = ", JSON.stringify(this.state.videos[0].id));
    //logs : ERROR :
    // >> states = ncaught TypeError: Cannot read property 'id' of undefined
    // at App.render (App.js:50)
    // at finishClassComponent (react-dom.development.js:13193)
    // at updateClassComponent (react-dom.development.js:13155)

    return (
      <div className="App">
        {
          // using an NPM package for displaying YouTube Videos
          // will add this back when I get the videoIds pulling correctly..
          //<YouTube
          //   videoId={this.state.videos[1].videoId}
          //   opts={opts}
          //   onReady={this._onReady}
          // />
        }
      </div>
    );
  }
}

export default App;

标签: javascriptarraysjsonreactjsyoutube-api

解决方案


您的请求是异步的,因此不会在第一次渲染时设置视频。this.state.videos[0]会给出undefined,并且试图访问id它会导致你的错误。

相反,您可以保留一个额外的状态,并在您的网络请求完成之前进行loading渲染。null

例子

class App extends Component {
  state = { videos: [], loading: true };

  componentDidMount() {
    var that = this;
    var API_key = "MY API KEY IS HERE (working) ";
    var channelID = "UCs3o4RhBiP2wcwqkZR2QVLw";
    var maxResults = 10;
    var url =
      "https://www.googleapis.com/youtube/v3/search?key=" +
      API_key +
      "&channelId=" +
      channelID +
      "&part=snippet,id&order=date&maxResults=" +
      maxResults;

    fetch(url)
      .then(function(response) {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then(function(data) {
        that.setState({ videos: data.items, loading: false });
      })
      .catch(error => {
        console.error(error);
      });
  }

  render() {
    const { loading, videos } = this.state;

    if (loading) {
      return null;
    }

    return (
      <div className="App">
        <YouTube
          videoId={videos[1].id.videoId}
          opts={{
            height: "390",
            width: "640",
            playerVars: {
              autoplay: 1
            }
          }}
          onReady={this._onReady}
        />
      </div>
    );
  }
}

推荐阅读