Vadim Novozhilov
Vadim Novozhilov

Reputation: 855

Can't set state in React using hooks

I'm working on a fairly simple app to learn React Hooks and I got stuck. I want to fetch and display data from specific Spotify playlist. So far, this is my component:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function SongsList() {
    const [data, setData] = useState({ songs: [] });
    const [isLoading, setIsLoading] = useState(false);

    useEffect(() => {
        const fetchData = async () => {
            setIsLoading(true);
            const result = await axios.get('https://api.spotify.com/v1/playlists/37i9dQZEVXbMDoHDwVN2tF/tracks', {
                    headers: {
                        Authorization: 'Bearer sometoken'
                    }
                }
            )
            setData(result.data.items);
            console.log(result.data.items);
            setIsLoading(false);
        }
        fetchData();
    }, [])

    return (
        <div>
            {isLoading ? (
                <div>Loading...</div>
            ) : (
                <div>
                    {data.songs.map(song => (
                        <li key={song.track.id}>
                            <p>{song.track.artist}</p>
                        </li>
                    ))}
                </div>
            )
            }
        </div>
    )
}

export default SongsList;

This code throws an error saying TypeError: data.songs is undefined and I can't understand why is that. Please note that in my fetchData function I have a log from my console tu ensure that I at least fetch any data: console.log(result.data.items);. It gives me the correct output: my console log output

But my data in useState output seems to be never setted or setted wrong. Can you please help me to understand what is wrong about my code? Thanks in advance!

Upvotes: 0

Views: 87

Answers (3)

Afia
Afia

Reputation: 683

Considering that your component is mounted before the request is made, you should also check for the presence of the data before rendering. like below:

{ data && data.songs.map(song => (
   <li key={song.track.id}>
       <p>{song.track.artist}</p>
   </li>
   )) 
}

Upvotes: 1

akhtarvahid
akhtarvahid

Reputation: 9779

Change to this setData({songs: result.data.items});

Because you are defining your songs array in object.

Upvotes: 0

Muhammad Zeeshan
Muhammad Zeeshan

Reputation: 4748

You are not setting the data right way. You have declared data as an object which contains songs. You should set songs like:

setData({ songs: result.data.items });

And this will work for you.

Upvotes: 2

Related Questions