Using Spotify Web Playback SDK with React
Asked Answered
S

1

7

Spotify has a new feature in beta supporting full song playback in browser, Web Playback SDK. The documentation shows an example of immediately initializing a player using script tags in the main HTML file. This requires an access token to be set immediately in the script. My issue is that I am creating a React app and I only want to initialize a player if a user clicks a button to login to their Spotify account. In order to load in a script only once this event occurs, I am using react-load-script. The flow I want is: a user clicks a button to login to their Spotify account, once their login is authenticated by Spotify my app receives an access token, the web playback script is then loaded, once the script is loaded a callback function is called and the player is initialized using the access token.

The problem is that the Spotify object does not exist until the spotify-player script has been loaded in. When the handleScriptLoad callback is actually invoked, the Spotify object is defined, but when the code is being compiled, it is not. Does anyone have any ideas how to get around this problem?

Code sample from the relevant React component:

import Script from 'react-load-script'

...

handleScriptLoad = () => {
const token = this.props.tokens.access
const player = new Spotify.Player({      // Spotify is not defined until 
  name: 'Spotify Web Player',            // the script is loaded in 
  getOAuthToken: cb => { cb(token) }
})

player.connect()
}

...

in my React component's render method:

<Script 
  url="https://sdk.scdn.co/spotify-player.js" 
  onError={this.handleScriptError} 
  onLoad={this.handleScriptLoad}
/>
Soak answered 4/12, 2017 at 17:5 Comment(1)
Possible duplicate of How do I return the response from an asynchronous call?Chemnitz
P
4

In theory, it is possible.

The Web Playback SDK will asynchronously load the window.Spotify object in our SDK via an external script. So, waiting for the object to be defined should solve the problem:

handleScriptLoad = () => {
  return new Promise(resolve => {
    if (window.Spotify) {
      resolve();
    } else {
      window.onSpotifyWebPlaybackSDKReady = resolve;
    }
  });
}

That should solve your problem.

Porcia answered 14/12, 2017 at 17:34 Comment(6)
Thanks Bilawal Hameed! I actually solved the issue simply by defining the player as window.Spotify.Player instead of Spotify.Player. This effectively ignores that window.Spotify is undefined until the script is loaded the handleScriptLoad function is run.Soak
Interesting. Wouldn't that throw an error as window.Spotify would be undefined and you're trying to call a method on it?Porcia
It doesn't throw an error. Apparently the Player method is not getting checked at compile time, so it doesn't matter that Spotify is initially undefined.Soak
The SDK defines window.Spotify.Player, so whenever we call Spotify.Player it will attempt to look for it locally and globally. And once the SDK loads, it will be defined globally. The two should be synonymous, unless you've overridden it locally.Porcia
I agree, but for some reason it fails to compile when it is defined as Spotify.Player but it works fine when it is defined as window.Spotify.Player. My only guess was that at compilation time it is not checking that Player is actually a method on Spotify, only that Spotify is a valid object. In any case, I ended up using the solution that you presented as it is more robust and I actually understand it, thanks for your help.Soak
That makes sense! Usually it's a good idea to just specify window.Spotify.Player like you have done. Glad that you found it useful! Feel free to reach out if you have any other questions, I work at Spotify :)Porcia

© 2022 - 2024 — McMap. All rights reserved.