0

I am having a bit of trouble with my project with spotify, every time I try to search for an artist I get this message: illegal redirect_uri. I also get a list of issues that I am boggled with. Would anyone have any advice? Here is my code.

src\Components\SearchBar\SearchBar.js Line 25:5: Duplicate name ‘handleTermChange’ no-dupe-class-members

src\util\Spotify.js Line 1:7: ‘clientId’ is assigned a value but never used no-unused-vars Line 2:7: ‘redirectUri’ is assigned a value but never used no-unused-vars Line 25:31: Unexpected template string expression no-template-curly-in-string Line 31:15: ‘accessToken’ is assigned a value but never used no-unused-vars Line 32:22: Unexpected template string expression no-template-curly-in-string Line 34:27: Unexpected template string expression no-template-curly-in-string Line 57:15: ‘accessToken’ is assigned a value but never used no-unused-vars Line 58:41: Unexpected template string expression no-template-curly-in-string Line 64:13: ‘userId’ is assigned a value but never used no-unused-vars Line 65:27: Unexpected template string expression no-template-curly-in-string Line 72:23: ‘playlistId’ is assigned a value but never used no-unused-vars

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});
    }

    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" onClick={this.search} >SEARCH</button>
</div>
        )
    }
}

export default SearchBar;
const clientId = '5e56a43c5001426189eda044053e2d30';
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]);
            //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 => {
            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 fetch('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/${user_id}/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',
                {
                    headers: headers,
                    method: 'POST',
                    body: JSON.stringify({Uris: trackUris})
                });
            })
        })
    }
}

export default Spotify;
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 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(searchResults => {
      this.setState({searchResults: searchResults})
    })
  }


  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 playstName={this.state.playlistName}
        playlistTracks={this.state.playlistTracks} 
        onRemove = {this.removeTrack}
        onNameChange ={this.updatePlaylistName}
        onSave = {this.savePlaylist} /> 
    </div>
  </div>
</div>
    )
  }
}

export default App;
  • Most of the issues you are showing there come from [eslint](https://eslint.org/), which comes automatically configured when using [Create React App](https://create-react-app.dev/). For instance "src\Components\SearchBar\SearchBar.js Line 25:5: Duplicate name ‘handleTermChange’ no-dupe-class-members"; in that file at that line you can see you have defined `handleTermChange` twice in a row. Eslint basically is configured to find common mistakes or antipatterns and warn you about them to keep your code clean and maintainable. – Alexander Nied Sep 09 '21 at 03:25
  • All of those errors/warnings are fairly self-explanatory. For example: you have _two_ `handleTermChange` methods in your `SearchBar` component which is what _"Duplicate name ‘handleTermChange’ no-dupe-class-members"_ is warning you about. – Andy Sep 09 '21 at 03:25
  • As for the "illegal redirect_uri" error, [the SO post "Spotify API Illegal redirect_uri"](https://stackoverflow.com/questions/49418717/spotify-api-illegal-redirect-uri) may contain some useful information. – Alexander Nied Sep 09 '21 at 03:27
  • 1
    Also worth noting on the point of eslint-- most editors can be configured to surface this errors and warnings directly in the editor itself, so you can see them and resolve them immediately instead of waiting for your build process to log them to the terminal and/or browser console. – Alexander Nied Sep 09 '21 at 03:29
  • Thank you very much! This is one of the solutions that solved my problem! –  Sep 10 '21 at 04:07

2 Answers2

0

Your Template literals is wrongly declare, they all need to start and end with a backtick (`)

It should be:

const accessUrl = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectUri}`

With (`) not (')

And so on with your other Template literals, it should all start and end with backticks (`);

return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`,
Authorization:`Bearer ${accessToken}`

And so on...

Also, remove one of the handleTermChange functions.

Ryan Le
  • 7,708
  • 1
  • 13
  • 23
  • Thank you very much! This is one of the solutions that solved my problem! –  Sep 10 '21 at 04:06
0

First, you have 2 handleTermChange. Remove one of theme.

Second, you use Template literals wrong way. So clientId will not to use. Just update like this with {``}

const accessUrl = {`https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectUri}`}
Viet
  • 12,133
  • 2
  • 15
  • 21
  • Thank you very much! This is one of the solutions that solved my problem! –  Sep 10 '21 at 04:07