Hi, I got to about step 95 of the Jamming project and when I click the search button I am not receiving any data from Spotify and no results show up when I search for a song. Could someone look over my code and tell me what I am possibly doing wrong?
Sotify.js
const clientId = '***';
const redirectUri = 'http://localhost:3000';
let accessToken;
const Spotify = {
getAccessToken() {
if (accessToken) {
return accessToken;
}
// check for an access token match
const accessToeknMatch = window.location.href.match(/access_token=([^&]*)/);
const expiresInMatch = window.location.href.match(/expires_in=([^&]*)/);
if (accessToeknMatch && expiresInMatch) {
accessToken = accessToeknMatch[1];
const expiresIn = Number(expiresInMatch[1]);
// This clears the parameters, allowing 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.artist[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/${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 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})
})
console.log('working');
}
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.stae = {
term: ''
}
this.search = this.search.bind(this);
this.handleTermChange = this.handleTermChange.bind(this);
}
search() {
this.props.onSearch(this.state.term);
}
handleTermChange(e) {
this.setState({ term: e.target.value });
}
render() {
return (
<div className="SearchBar">
<input onChange={this.handleTermChange} placeholder="Enter A Song, Album, or Artist" />
<button onClick={this.search} 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(e) {
this.props.onNameChange(e.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 './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;
Track.js
import React from "react";
import './Track.css';
class Track extends React.Component {
constructor(props) {
super(props);
this.addTrack = this.addTrack.bind(this);
this.removeTrack = this.removeTrack.bind(this);
}
renderAction() {
if (this.props.isRemoval) {
return <button className="Track-action" onClick={this.removeTrack}>-</button>
} else {
return <button className="Track-action" onClick={this.addTrack}>+</button>
}
}
addTrack() {
this.props.onAdd(this.props.track);
}
removeTrack() {
this.props.onRemove(this.props.track);
}
render() {
return (
<div className="Track">
<div className="Track-information">
<h3>{this.props.track.name}</h3>
<p>{this.props.track.artist} | {this.props.track.album}</p>
</div>
{this.renderAction()}
</div>
)
}
}
export default Track;
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;