How to display a map function from a fetch REACT.js

Viewed 323

This is my first time using this website so bear with me... I am trying to display an array of 10 youtube videos from a playlist using the youtube api. So far I am able to console.log the json data from the api. Although the issue arrives when I attempt to display that json data in my react app using inside a map function.

Here is all my code :

import React, { Component } from "react";
import './Videos.css';
import VideosCP from '../Pages/VideosPage/VideosSearch'
import youtubeSearch from "../../api/youtubeSearchApi";
import VideosList from "../Pages/VideosPage/VideoList";

const YOUTUBE_PLAYLIST_ITEMS_API = 'https://www.googleapis.com/youtube/v3/playlistItems';

let url = `${YOUTUBE_PLAYLIST_ITEMS_API}?part=snippet&playlistId=myPlaylistId&maxResults=10&key=myYoutubekey`

function Demo() {
    
}

class Videos extends Component{

    state = {
        videoMetaInfo:[],
        selectedVideoId: null
    }

    onVideoSelected = videoId => {
        this.setState({
            selectedVideoId:videoId
        })
    }

    onSearch = async keyword => {
        const response = await youtubeSearch.get("/search",{
            params:{
                q:keyword
            }
        })
        console.log(this.state);

        this.setState({
            videoMetaInfo: response.data.items,
            selectedVideoId: 'Nl3DoewG3Co'
        })
    }

    playlistRender = async () => {
        const data =  await fetch(url);
        let commits = await data.json();
        console.log('data', commits)

    }

    render(){

        const Data = ({data}) => {
            data = this.playlistRender()
            const results = data.items.map((item)=>{
                const {id, snippet = {}} = item
                const title = snippet
                return(
                    <li key={id}>
                        <h3>{title}</h3>
                    </li>
                )
            });
            return results
        }

        return(

            <div className="wrapper">
                <div className="wrapper-inner scroll">
                    <VideosCP onSearch={this.onSearch}/>
                    <VideosList onVideoSelected={this.onVideoSelected}
                    data={this.state.videoMetaInfo}/>
                    <ul>
                       <Data/>
                    </ul>
                </div>
            </div>
        );
    }
}

export default Videos

The code compiles fine in the terminal but once inside the browser it spits the error : "Cannot read property 'map' of undefined".

Hence, the error is caused by this line which states : data.items.map((item)=>{

What's even more weirder is that the console in the browser recognizes that there is an "items" in the array. Why is the browser spitting this error at me? Can it not map the items? If so why not? And how is this error fixable?

I have tried everything so far and this is the closest I've gotten but yet no results.

Please help me, stack overflow is my only hope...

1 Answers

The data you're loading from the API is stateful, so you'll want to set it to state once it's loaded. Then, you can map over this stateful information once it exists.

I also added a componentDidMount method call to make sure we call the API once the component mounts.

class Videos extends Component{

    state = {
        videoMetaInfo:[],
        selectedVideoId: null,
        commits: []
    }

    onVideoSelected = videoId => {
        this.setState({
            selectedVideoId:videoId
        })
    }

    onSearch = async keyword => {
        const response = await youtubeSearch.get("/search",{
            params:{
                q:keyword
            }
        })
        console.log(this.state);

        this.setState({
            videoMetaInfo: response.data.items,
            selectedVideoId: 'Nl3DoewG3Co'
        })
    }

    playlistRender = async () => {
        const data =  await fetch(url);
        let commits = await data.json();
        this.setState({ commits });
    }

    componentDidMount() {
        this.playlistRender();
    }

    render(){
        return(
            <div className="wrapper">
                <div className="wrapper-inner scroll">
                    <VideosCP onSearch={this.onSearch}/>
                    <VideosList onVideoSelected={this.onVideoSelected}
                    data={this.state.videoMetaInfo}/>
                    <ul>
                        {this.state.commits.map((item) => {
                            const {id, snippet = {}} = item
                            const title = snippet
                            return (
                                <li key={id}>
                                    <h3>{title}</h3>
                                </li>
                            )
                        })}
                    </ul>
                </div>
            </div>
        );
    }
}

export default Videos
Related