Jammming - TypeError: Cannot read property 'id' of undefined - Can't save playlist

I just finished the Jammming project from the Create a React Web App Skill Path, I managed to do the whole accessToken Spotify connection and send querys to the API. What I cannot do is save the playlist in my Spotify account, because when I press the SAVE TO SPOTIFY button, I get this error:

Spotify.js:66 Uncaught (in promise) TypeError: Cannot read property 'id' of undefined
    at Spotify.js:66

These are my files

App.js

import './App.css';
import { Playlist } from '../Playlist/Playlist';
import { SearchBar } from '../SearchBar/SearchBar';
import { SearchResults } from '../SearchResults/SearchResults';
import Spotify from '../../util/Spotify';
import React from 'react';


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      searchResults: [],
      playlistName: 'My Playlist',
      playlistTracks: []
    };
    this.addTrack = this.addTrack.bind(this);
    this.removeTrack = this.removeTrack.bind(this);
    this.updatePlaylistName = this.updatePlaylistName.bind(this);
    this.savePlaylist = this.savePlaylist.bind(this);
    this.search = this.search.bind(this);
  }

  addTrack(track) {
    let tracks = this.state.playlistTracks;
    if (tracks.find(savedTrack => savedTrack.id === track.id)) {
      return;
    }

    tracks.push(track);
    this.setState({playlistTracks: tracks});
  }

  removeTrack(track) {
    let tracks = this.state.playlistTracks;
    tracks = tracks.filter(currentTrack => currentTrack.id !== track.id);

    this.setState({ playlistTracks: tracks});
  }

  updatePlaylistName(name) {
    this.setState({
      playlistName: name
    });
  }

  savePlaylist() {
    const trackUris = this.state.playlistTracks.map(track => track.uri);
    Spotify.savePlaylist(this.state.playlistName, trackUris).then(() => {
      this.setState(
        { playlistName: 'New Playlist', 
          playlistTracks: [] 
        })
    })
  }

  search(term) {
    Spotify.search(term).then(tracks => this.setState({searchResults: tracks}));
  }

  render() {
    return (
      <div>
        <h1>Ja<span className="highlight">mmm</span>ing</h1>
        <div className="App">
          <SearchBar onSearch={this.search} />
          <div className="App-playlist">
            <SearchResults  searchResults={this.state.searchResults}
              onAdd={this.addTrack} />
            <Playlist playlistName={this.state.playlistName}
              playlistTracks={this.state.playlistTracks}
              onRemove={this.removeTrack}
              onNameChange={this.updatePlaylistName}
              onSave={this.savePlaylist} />
          </div>
        </div>
      </div>
    )
  }
}

export default App;

Spotify.js

const clientId = ''; //API Key deleted intentionally for his post
const redirectUri = 'http://alejammming.surge.sh';

let accessToken;

let Spotify = {
    getAccessToken() {
        if (accessToken) {
            return accessToken;
        } 

        // check for access token match
        const accessTokenMatch = window.location.href.match(/access_token=([^&]*)/);
        const expiresInMatch = window.location.href.match(/expires_in=([^&]*)/);

        if (accessTokenMatch && expiresInMatch) {
            accessToken = accessTokenMatch[1];
            const expiresIn = Number(expiresInMatch[1]);
            // This clears the parameters, allowing us to grab a new access
            // token when it expires
            window.setTimeout(() => accessToken = '', expiresIn * 1000);
            window.history.pushState('Access Token', null, '/');
            return accessToken;
        } else {
            const accessUrl = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectUri}`;
            window.location = accessUrl;
        }
    },

    search(term) {
        const accessToken = Spotify.getAccessToken();
        return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
          headers: {
            Authorization: `Bearer ${accessToken}`
          }
        })
          .then(response => response.json())
          .then(jsonResponse => {
            if (!jsonResponse.tracks) {
              return [];
            }
            return jsonResponse.tracks.items.map(track => ({
              id: track.id,
              name: track.name,
              artist: track.artists[0].name,
              album: track.album.name,
              uri: track.uri
            }));
          });
      },

      savePlaylist(name, trackUris) {
        if (!name || trackUris.length) {
            return;
          };
          const accessToken = Spotify.getAccessToken();
          const headers = { Authorization: `Bearer ${accessToken}` };
          let userId;
  
          return fetch('https://api.spotify.com/v1/me', { headers: headers })
            .then(response => { 
                return response.json(); 
            })
            .then(jsonResponse => {
              userId = jsonResponse.id; // <- here's where it points out the error is, but I'm not sure why
              return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, 
              {
                headers: headers,
                method: 'POST',
                body: JSON.stringify({ name: name })
              })
                .then(response => {
                     return response.json()
                })
                .then(jsonResponse => {
                  const playlistId = jsonResponse.id;
  
                  return fetch(
                    `https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks`,
                    {
                      headers: headers,
                      method: 'POST',
                      body: JSON.stringify({ uris: trackUris })
                    }
                  );
                });
            });
        }
      };

export default Spotify;

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.