Jamming Project: Missing required parameter: client_id

Welp, I’m particularly stumped on this one. This project has me feeling pretty dumb considering the sheer amount of Javascript logic you were expected to know off hand without desperately following along with the walkthrough. I did pretty well right up to the very end, but for whatever reason my searches will not go through. I keep getting a ‘Missing required parameter: client_id’ error code when I attempt to hit the search button.

Also, for what it’s worth, I cannot for the life of me find the step that tells me to add an ‘onCilck’ prop to the rendered in . Nothing happens if you click the button without it, but for some reason the walkthrough video and the instructions seems to skip this step but it works for him anyway. Attached is the code for Spotify.js and SearchBar.js, the answer has to be somewhere in here but I’ve been beating my head against the wall for two full days stuck up on it. Help!
Spotify.js:


let accessToken;

const clientId = //My client Id is here and 100% correct

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

const Spotify= {

    getAccessToken() {
        if(accessToken) {
            return accessToken;
        } 

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

        if(accessTokenMatch && expiresInMatch) {
            let accessToken = accessTokenMatch[1];
            const expiresIn = Number(expiresInMatch[1]);
            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/${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;```

SearchBar.js:


import React from ‘react’;

import ‘./SearchBar.css’;

class SearchBar extends React.Component {

constructor(props) {

    super(props)

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

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

}

search(term) {

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

}

handleTermChange(event) {

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

}

render() {

    return (

        <div className="SearchBar">

<input placeholder=“Enter A Song, Album, or Artist”

    onChange={this.handleTermChange} />

SEARCH

    );

}

};

export default SearchBar;

If you check the browser’s console for errors, you’re going to see something like this:

image

Because you’re using backticks in the following code, the string ends up having the line-breaks and spaces from the indents of your code too:

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

So if we did a console.log(accessUrl), it would look like this:

https://accounts.spotify.com/authorize?
                                client_id=CLIENTIDHERE&response_type=token
                                &scope=playlist-modify-public&redirect_uri=http://localhost:3000/

Browsers will encode all the spaces to %20 since the character code of a space is 32 and the hex of that is 0x20. That’s why you see so many %20’s in the URL. Spotify APIs can’t handle all that extra stuff being thrown at it.

The easiest solution here will be to have the URL on one line. Otherwise you can use a combination of concatenation and template literals or just concatenation.

1 Like

That totally did it! Thank you so much!

1 Like

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