Jamming # 11

For #11 on the project Jamming, it mentions to add a return statement inside a .render() method. However, App.js isn’t a React component so I’m not really sure what I am supposed to do here.

It would help to share your code so we can understand what you are doing and can help you.

I believe App.js is a React component, and while the unedited file from the create-react-app template is in the format of a functional component (without a render method), the tutorial instructs to create a class component (which will include a render method and return statement).

There is also a “walkthrough” video for this exercise which might make things clearer… https://youtu.be/DH991Dzb9iE?t=779

I got to step 99, but when I type surge, I’m not sure what it means when it asks me to enter an email and password. Am I supposed to register them somewhere first, or do I just type my email and then a password after?

I was able to enter them but now i’m getting an illegal redirect_uri error when i type it into the browser.

Here is my code for Spotify.js except clientId :

const redirectUri = ‘sam_jam.surge.sh’;
const spotifyUrl = https://accounts.spotify.com/authorize?response_type=token&scope=playlist-modify-public&client_id=${clientId}&redirect_uri=${redirectUri};
let accessToken = undefined;
let expiresIn = undefined;

const Spotify = {
getAccessToken() {
if (accessToken) {
return accessToken;
}
const urlAccessToken = window.location.href.match(/access_token=([^&])/);
const urlExpiresIn = window.location.href.match(/expires_in=([^&]
)/);
if (urlAccessToken && urlExpiresIn) {
accessToken = urlAccessToken[1];
expiresIn = urlExpiresIn[1];
window.setTimeout(() => accessToken = ‘’, expiresIn * 1000);
window.history.pushState(‘Access Token’, null, ‘/’);
} else {
window.location = spotifyUrl;
}
},

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

savePlaylist(name, trackUris) {
if (!name || !trackUris || trackUris.length === 0) return;
const userUrl = ‘https://api.spotify.com/v1/me’;
const headers = {
Authorization: Bearer ${accessToken}
};
let userId = undefined;
let playlistId = undefined;
fetch(userUrl, {
headers: headers
})
.then(response => response.json())
.then(jsonResponse => userId = jsonResponse.id)
.then(() => {
const createPlaylistUrl = https://api.spotify.com/v1/users/${userId}/playlists;
fetch(createPlaylistUrl, {
method: ‘POST’,
headers: headers,
body: JSON.stringify({
name: name
})
})
.then(response => response.json())
.then(jsonResponse => playlistId = jsonResponse.id)
.then(() => {
const addPlaylistTracksUrl = https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks;
fetch(addPlaylistTracksUrl, {
method: ‘POST’,
headers: headers,
body: JSON.stringify({
uris: trackUris
})
});
})
})
}
};

export default Spotify;


Here is my code for App.js:

import React from ‘react’;

import { BaseComponent } from ‘…/BaseComponent/BaseComponent’;
import Spotify from ‘…/…/util/Spotify’;
import SearchBar from ‘…/SearchBar/SearchBar’;
import SearchResults from ‘…/SearchResults/SearchResults’;
import Playlist from ‘…/Playlist/Playlist’;
import ‘./App.css’;

Spotify.getAccessToken();

class App extends BaseComponent {
constructor(props) {
super(props);
this.state = {
searchResults: ,
playlistName: ‘My playlist’,
playlistTracks:
}
this._bind(‘updatePlaylistName’, ‘addTrack’, ‘removeTrack’, ‘savePlaylist’, ‘search’);
}

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

addTrack(track) {
if (!this.state.playlistTracks.find(playlistTrack => playlistTrack.id === track.id)) {
this.setState(prevState => ({
playlistTracks: […prevState.playlistTracks, track]
}));
}
}

removeTrack(track) {
this.setState({
playlistTracks: this.state.playlistTracks.filter(playlistTrack => playlistTrack.id !== track.id)
});
}

savePlaylist() {
const trackUris = this.state.playlistTracks.map(playlistTrack => playlistTrack.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 (


Jammming










);
}
}

export default App;

I ran into some redirect issues too, and what I had to do to resolve my issues:

  1. Make sure your redirectUri ends with a trailing ‘/’
  2. Make sure you’ve updated within your Spotify app settings (on the spotify site) to have the same redirectUri (previously we set it to localhost:3000).

It may or may not make a difference, but my spotifyUrl had the clientId earlier in the web address:

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

I didn’t use surge to deploy so I can’t help with that, but yes I imagine you need to create an account with them to use their services.

I can see a few differences in your code to mine, but it is hard to read when it hasn’t been formatted. Here’s a little info on formatting your code. How do I format code in my posts? There is a button in the text editor that can help, or use the backticks.