DSteman
DSteman

Reputation: 1658

Struggling with promises and async functions in React

I'm working on a React project where I have a function that fetches paginated data recursively. This function is defined in another function, where I activate the loading screen with showLoading() at the start, where I'm calling the fetching data function in the body and deactivate the loading screen with hideLoading() at the end. The function:

const fetchPlaylist = (playlistId) => {
    showLoading()
    const getPlaylistDataRecursively = (url) => {
      fetch('/spotify/get-track-ids', {headers: {
        'url': url
      }})
      .then(response => response.json())
      .then(data => {
        console.log(data)

        setTitles(data.title)
        setArtists(data.artist)
        setFeatures(data.features)
        setIds(data.track_ids)

        if (data.next_url) {
          const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
          getPlaylistDataRecursively(next_url)
        }
      })
    }
    getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
    hideLoading()
  }

I believe I can attach a promise to the getPlaylistDataRecursively call with the then keyword but I'm getting a TypeError: Cannot read property 'then' of undefined. Probably because getPlaylistDataRecursively doesn't return anything. How do I make sure that hideLoading is called after getPlaylistDataRecursively is done?

Upvotes: 0

Views: 68

Answers (1)

StriplingWarrior
StriplingWarrior

Reputation: 156459

You always need to return a promise.

const fetchPlaylist = (playlistId) => {
    showLoading()
    const getPlaylistDataRecursively = (url) => {
      return fetch('/spotify/get-track-ids', {headers: {
        'url': url
      }})
      .then(response => response.json())
      .then(data => {
        console.log(data)

        setTitles(data.title)
        setArtists(data.artist)
        setFeatures(data.features)
        setIds(data.track_ids)

        if (data.next_url) {
          const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
          return getPlaylistDataRecursively(next_url)
        }
      })
    }
    return getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
      .then(() => hideLoading());
  }

Or, using async/await:

const fetchPlaylist = async (playlistId) => {
    showLoading()
    const getPlaylistDataRecursively = async (url) => {
      const response = await fetch('/spotify/get-track-ids', {headers: {
        'url': url
      }})
      const data = response.json()
      console.log(data)
      setTitles(data.title)
      setArtists(data.artist)
      setFeatures(data.features)
      setIds(data.track_ids)
      if (data.next_url) {
        const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
        await getPlaylistDataRecursively(next_url)
      }
    }
    await getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
    hideLoading()
  }

Upvotes: 2

Related Questions