Jamming step 95 Not showing search results and error when clicking save playlist

So I’ve been at it for hours trying to get this to work (I’ve tried adding an onClick to the search but that didn’t fix anything) and going back to the video to redo the entire spotify.js but still no luck. Please help. I don’t get an error when trying the search just nothing happens.

As for the error when clicking save playlist it says TypeError: Cannot read property ‘then’ of undefined and refers me to savePlaylist method on App.js but I’ve also rewritten this intently following the video but no luck. Please help :frowning:

Spotify.js

const clientId = ******;

const redirectUri = 'http://localhost:3000';

let accessToken;

const 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]);

            //Clear the parameters from the URL

            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 => {

            return 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 ('https://api.spotify.com/v1/me' , { headers: headers }

        ).then(response => response.json()

        ).then(jsonResponse => {

            userId = jsonResponse.id;

            return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, 

             {

                headers: headers,

                method: 'POST',

                body: JSON.stringify({ name: name})

             }).then(response => 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;
App.js
import React from 'react';

import './App.css';

import SearchBar from '../SearchBar/SearchBar';

import SearchResults from '../SearchResults/SearchResults';

import Playlist from '../Playlist/Playlist';

import Spotify from '../../util/Spotify';

class App extends React.Component {

  constructor(props) {

    super(props);

    

    this.state = { 

      searchResults: [],

      playlistName: 'My React 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);

  }

// step 42 add track

  addTrack(track) {

    let tracks = this.state.playlistTracks;

    if(tracks.find(savedTrack => savedTrack.id === track.id))

      {

        return;

      } else {

          tracks.push(track);

          this.setState({playlistTracks: tracks});

        }

      

  }

  //step 49 remove track

  removeTrack(track) {

       let tracks = this.state.playlistTracks;

       tracks = tracks.filter( currentTrack => currentTrack.id !== track.id);

       this.setState({playlistTracks: tracks});      

  }

  //Step 57 Update Name of Playlist

  updatePlaylistName(name) {

        this.setState({playlistName: name});

  } 

  //Step 63 Save Your New Playlist

  savePlaylist() {

    const trackUris = this.state.playlistTracks.map(track => track.uri);

    Spotify.savePlaylist(this.state.playlistName, trackUris).then(() => {

      this.setState({

        playlistName: 'New Playlist',

        playlistTracks: []

      })

    })

  }

  //Update Search Results of User

  search(term) {

    Spotify.search(term).then(searchResults => {

      this.setState({searchResults: searchResults})

    })

  }

  //Render Function

  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

SearchBar.js

import React from 'react';

import './SearchBar.css';

class SearchBar extends React.Component {

    constructor(props) {

        super(props);

        this.state = {

            term: ''

        }

        this.search = this.search.bind(this);

        this.handleTermChange = this.handleTermChange.bind(this);

    }

    search() {

        this.props.onSearch(this.state.term);

    }

    handleTermChange(event) {

        this.setState({term: event.target.value});

    }

    render() {

        return (

            <div className="SearchBar">

                <input onChange={this.handleTermChange}

                        placeholder="Enter A Song, Album, or Artist" 

                        />

                <button className="SearchButton" >SEARCH</button>

            </div>

        )

    }

};

export default SearchBar;

Playlist.js

import React from 'react';

import './Playlist.css';

import TrackList from '../TrackList/TrackList';

class Playlist extends React.Component {

    constructor(props) {

        super(props);

        this.handleNameChange = this.handleNameChange.bind(this);

    }

    handleNameChange(event) {

        this.props.onNameChange(event.target.value);

        }

    

    render() {

        return (

            <div className="Playlist">

                <input defaultValue={'New Playlist'}

                        onChange={this.handleNameChange}/>

                <TrackList tracks={this.props.playlistTracks}

                            onRemove={this.props.onRemove}

                            isRemoval={true}/>

                <button className="Playlist-save" onClick={this.props.onSave}>SAVE TO SPOTIFY</button>

            </div>

        )

    }

}

export default Playlist;

Tracklist.js

import React from 'react';

import SearchResults from '../SearchResults/SearchResults';

import './TrackList.css';

import Track from '../Track/Track'

class TrackList extends React.Component {

    render() {

        return (

            <div className="TrackList">

                {

                    this.props.tracks.map(track =>{

                        return <Track track={track}

                                      key={track.id}

                                      onAdd={this.props.onAdd}

                                      onRemove={this.props.onRemove}

                                      isRemoval={this.props.isRemoval}

                        />

                    })

                }

            </div>

        )

    }

}

export default TrackList

SearchResults.js

import React from 'react';

import './SearchResults.css';

import TrackList from '../TrackList/TrackList';

class SearchResults extends React.Component {

    render() {

        return (

            <div className="SearchResults">

                <h2>Results</h2>

                <TrackList tracks={this.props.searchResults}

                       onAdd={this.props.onAdd}

                       isRemoval={false}/>

            </div>

        )

    }

}

export default SearchResults;

I got the same problem …
been working for the past 2 days still no luck
can anyone help…please

Seems to be an issue with the access token function. I’m working on fixing it now but try below and see if that works for you.

  1. Log your access token to the console and see what you get. Mine was undefined which caused a 401 error on Spotify API.
  2. Paste the access token from the address bar into the code.

when i try to debug it is showing my accessToken is undefined…
what should i do?

Can you post your Spotify code?

For me, I had the RegEx in quotes for accessTokenMatch and expiresIn which doesn’t work.