Home > Software engineering >  Even though I filled the state in React, it looks empty in the render
Even though I filled the state in React, it looks empty in the render

Time:07-22

Definitely data is coming from the API. I checked with the console log, but even though I fill the data in useEffect, it doesn't detect the data in state in render. What is the solution?

const Trends = () => {

    const [videoList, setVideoList] = useState([]);

    useEffect(()=>{
        getYoutubeList()
        .then(resp=>{
            setVideoList(...resp);
        })
        // https://www.youtube.com/watch?v=
    },[])

    return(
        <>
        <div className="content">
            <div className="section-header">
                <h1>Video Gallery</h1>
            </div>
            <div className="video-gallery">
            {videoList.length > 0 && videoList.map((item, index)=>{
               return ( <div key={index} className="gallery-item" data-bs-toggle="modal" data-bs-target="#video-detail">
                    <img src={item.snippet.thumbnails.default.url} alt="Mount Rainier"/>
                    <div className="gallery-item-caption">
                        <h2>Mount Rainier</h2>
                        <p>14410 feet of adventure</p>
                    </div>
                </div> )
            })}
            </div>
        </div>


        </>
    );
}

export default Trends;

videoList:

[{
      "kind": "youtube#video",
      "etag": "paPvd888q5pA1ucvPMTiFkRZCBg",
      "id": "F3ciegocC5U",
      "snippet": {
        "publishedAt": "2022-07-18T18:04:01Z",
        "channelId": "UClW4jraMKz6Qj69lJf-tODA",
        "title": "NBA Youngboy - I Don't Talk",
        "description": "you ready for the album ??",
        "thumbnails": {
          "default": {
            "url": "https://i.ytimg.com/vi/F3ciegocC5U/default.jpg",
            "width": 120,
            "height": 90
          },
          "medium": {
            "url": "https://i.ytimg.com/vi/F3ciegocC5U/mqdefault.jpg",
            "width": 320,
            "height": 180
          },
          "high": {
            "url": "https://i.ytimg.com/vi/F3ciegocC5U/hqdefault.jpg",
            "width": 480,
            "height": 360
          }
        },
        "channelTitle": "YoungBoy Never Broke Again",
        "tags": [
          "YoungBoy Never Broke Again",
          "NBA YoungBoy",
          "YoungBoy Quando Rondo",
          "YoungBoy Leak",
          "Make No Sense YoungBoy",
          "Youngboy Lost Motives",
          "YoungBoy NBA Music Video",
          "YoungBoy Never Broke Again TOP",
          "nba youngboy top",
          "YoungBoy NBA TOP album",
          "7KTt4_M09Rw",
          "0C80BSgjb8M",
          "qChxuVxs8FA",
          "dYk-yCsuTUo",
          "6MCSr65d9Xc",
          "ALimx-H8C6s",
          "YoungBoy Never Broke Again Sincerely Kentrell",
          "Sincerely Kentrell",
          "Youngboy NBA Sincerely Kentrell",
          "Sincerely Kentrell album",
          "YBNBA Sincerely Kentrell",
          "YB Sincerely Kentrell",
          "Kentrell"
        ],
        "categoryId": "10",
        "liveBroadcastContent": "none",
        "localized": {
          "title": "NBA Youngboy - I Don't Talk",
          "description": "you ready for the album ??"
        }
      }
    },
    {
      "kind": "youtube#video",
      "etag": "FLRfxdSvvXa2wcv1Sa9HODChcjk",
      "id": "_HP7Moy4cgM",
      "snippet": {
        "publishedAt": "2022-07-19T19:00:38Z",
        "channelId": "UChEYVadfkMCfrKUi6qr3I1Q",
        "title": "Kodak Black - Haitian Scarface [Official Music Video]",
        "description": "Kodak Black -  Haitian Scarface [Official Music Video]\n'Back For Everything OUT NOW! \nStream/Download: https://music.apple.com/us/album/back-for-everything/1608934589\n \nSubscribe for more official content from Kodak Black:\nhttps://Atlantic.lnk.to/KBsubscribe\n\nFollow Kodak Black\nhttps://twitter.com/KodakBlack1k\nhttps://facebook.com/TheRealKodakBlack\nhttps://instagram.com/kodakblack\nhttps://soundcloud.com/kodak-black\nhttps://open.spotify.com/artist/46SHBwWsqBkxI7EeeBEQG7\n\nThe official YouTube channel of Atlantic Records artist Kodak Black. Subscribe for the latest music videos, performances, and more.\n\n#KodakBlack #HappyBirthdayKodak #BackForEverything",
        "thumbnails": {
          "default": {
            "url": "https://i.ytimg.com/vi/_HP7Moy4cgM/default.jpg",
            "width": 120,
            "height": 90
          },
          "medium": {
            "url": "https://i.ytimg.com/vi/_HP7Moy4cgM/mqdefault.jpg",
            "width": 320,
            "height": 180
          },
          "high": {
            "url": "https://i.ytimg.com/vi/_HP7Moy4cgM/hqdefault.jpg",
            "width": 480,
            "height": 360
          },
          "standard": {
            "url": "https://i.ytimg.com/vi/_HP7Moy4cgM/sddefault.jpg",
            "width": 640,
            "height": 480
          },
          "maxres": {
            "url": "https://i.ytimg.com/vi/_HP7Moy4cgM/maxresdefault.jpg",
            "width": 1280,
            "height": 720
          }
        },
        "channelTitle": "Kodak Black",
        "tags": [
          "kodak",
          "black",
          "kodak black",
          "atlantic records",
          "roll in peace",
          "codeine dreaming",
          "tunnel vision",
          "drowning",
          "transportin",
          "heart break kodak",
          "project baby 2",
          "Kodak Black Bill Israel",
          "Bill Israel",
          "Sniper",
          "Sniper Gang",
          "Hip Hop",
          "Rap",
          "Kodak Black I Knew It",
          "Kodak Bill Israel",
          "Kodak Black Easter in Miami",
          "Easter",
          "Easter in Miami",
          "Kodak Easter",
          "Kodak Black Haitian Boy Kodak",
          "Haitian Boy Kodak",
          "Kodak Black HBK",
          "HBK",
          "Kodak Black Happy Birthday Kodak",
          "Happy Birthday Kodak"
        ],
        "categoryId": "10",
        "liveBroadcastContent": "none",
        "localized": {
          "title": "Kodak Black - Haitian Scarface [Official Music Video]",
          "description": "Kodak Black -  Haitian Scarface [Official Music Video]\n'Back For Everything OUT NOW! \nStream/Download: https://music.apple.com/us/album/back-for-everything/1608934589\n \nSubscribe for more official content from Kodak Black:\nhttps://Atlantic.lnk.to/KBsubscribe\n\nFollow Kodak Black\nhttps://twitter.com/KodakBlack1k\nhttps://facebook.com/TheRealKodakBlack\nhttps://instagram.com/kodakblack\nhttps://soundcloud.com/kodak-black\nhttps://open.spotify.com/artist/46SHBwWsqBkxI7EeeBEQG7\n\nThe official YouTube channel of Atlantic Records artist Kodak Black. Subscribe for the latest music videos, performances, and more.\n\n#KodakBlack #HappyBirthdayKodak #BackForEverything"
        },
        "defaultAudioLanguage": "en"
      }
    }]

The videolist data comes from the YouTube API. I shoot with Axios. The data is definitely coming. I checked. I'm throwing it in state, but I guess the render and the runtime don't match. I don't know.

CodePudding user response:

You are not setting the state in the right way. The spread operator is used for arrays and objects.

Please use setVideoList([...resp]); to set the state.

CodePudding user response:

Solution

const Trends = () => {

    const [videoList, setVideoList] = useState([]);

    useEffect(()=>{
        getYoutubeList()
        .then(resp=>{
            setVideoList(resp); // <---- 1
        })
        // https://www.youtube.com/watch?v=
    },[])

    return (
    <div className="content">
        <div className="section-header">
        <h1>Video Gallery</h1>
        </div>
        <div className="video-gallery">
        {videoList.length > 0 &&
            videoList.map((item, index) => {
            return ( // <---- 2
                <div
                key={item.id} // <---- 3
                className="gallery-item"
                data-bs-toggle="modal"
                data-bs-target="#video-detail"
                >
                <img
                    src={item.snippet.thumbnails.default.url}
                    alt="Mount Rainier"
                />
                <div className="gallery-item-caption">
                    <h2>Mount Rainier</h2>
                    <p>14410 feet of adventure</p>
                </div>
                </div>
            );
            })}
        </div>
    </div>
    );
}

Explanation

1 - The server's response is already an array, and you can just set it without spreading its content. Ref. germanovs' response.

2 - When you use an arrow function with curly braces, a return statement is expected.

3 - You need to add a key prop when you create elements inside map. See React's list and keys documentation.

  • Related