Reputation: 1195
I'm a React beginner, so go easy on me..
I'm making a really really basic app right now that I will expand on later..
Right now I'm simply trying to get React to pull a JSON object from Youtube with channel data, store the returned list of videos (I guess in state?), and then pull the video IDs so that I can throw them in an object and randomize them for playback later.
My code is pulling the data alright, but at the moment I can't seem to access the "videoId" property of each video's ID... I can't for the life of me, understand why the video ID objects are accessible, but not their properties within..
It seems like YouTube API is returning an array of objects.. so I thought I should be able to do this:
videos[0].id.videoId
but this is giving errors... however videos[0].id seems to work, so I'm lost..
What am I doing wrong? Am I using state wrong? Am I accessing the object properties wrong?
See below for console logs in the example:
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;
Upvotes: 2
Views: 3282
Reputation: 112927
Your request is asynchronous, so the videos will not be set on first render. this.state.videos[0]
will give undefined
, and trying to access id
on that will result in your error.
You could instead e.g. keep an additional piece of state loading
and just render null
until your network request has finished.
Example
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>
);
}
}
Upvotes: 2