How to use Spotify 30sec previews with Expo React native app

I have been trying to use the Spotify API in my expo app but every tutorial or wrapper I find doesn't seem to work.

I would specifically like to access the 30-second song previews and track/song searching features.

If anyone could provide some guidance or point me towards a working demo of any kind that would be awesome.

Thanks!


Found parts of the solution in https://docs.expo.dev/guides/authentication/#spotify

const discovery = {
  authorizationEndpoint: 'https://accounts.spotify.com/authorize',
  tokenEndpoint: 'https://accounts.spotify.com/api/token',
};

var client_id = ''; // Your client id
var client_secret = ''; // Your secret


export default function spotifyLogin(props) {
    const [request, response, promptAsync] = useAuthRequest(
        {
            clientId: '',
            scopes: ['user-read-email', 'user-read-playback-state', 'playlist-modify-public','playlist-modify-private','playlist-modify-public','playlist-read-private','user-read-recently-played'],
            // In order to follow the "Authorization Code Flow" to fetch token after authorizationEndpoint
            // this must be set to false
            usePKCE: false,
            redirectUri: makeRedirectUri({
              //scheme: 'your.app'
              }),
          },
          discovery
    );
  
React.useEffect(() => {
  if (response?.type === 'success') {
    const { code } = response.params;
    //save code to local storage
    props.saveLogin(code)
    }
}, [response]);

return (
  <Button
    disabled={!request}
    title="Login"
    onPress={() => {
      promptAsync();
      }}
  />
);
  }

export const getFirstTokenData = async (code) => {
    var dataToSend = { 
      code: code,
      redirect_uri: makeRedirectUri(),
      grant_type: 'authorization_code'};
    //making data to send on server
    var formBody = [];
    for (var key in dataToSend) {
      var encodedKey = encodeURIComponent(key);
      var encodedValue = encodeURIComponent(dataToSend[key]);
      formBody.push(encodedKey + '=' + encodedValue);
    }
    formBody = formBody.join('&');
    //POST request
    var response = await fetch('https://accounts.spotify.com/api/token', {
      method: 'POST', //Request Type
      body: formBody, //post body
      headers: {
        //Header Defination
        'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')),
      },
    })
    try{
        return await response.json()
    }catch (error){
        console.log(error)
    }
    
}



export const getRefreshTokenData = async (refreshToken) => {
    console.log(refreshToken)
    console.log(refreshToken + " going in for refresh")
    var dataToSend = { 
        refresh_token : refreshToken,
        grant_type: 'refresh_token'};
    //making data to send on server
    var formBody = [];
    for (var key in dataToSend) {
        var encodedKey = encodeURIComponent(key);
        var encodedValue = encodeURIComponent(dataToSend[key]);
        formBody.push(encodedKey + '=' + encodedValue);
    }
    formBody = formBody.join('&');
    //POST request
    var response = await fetch('https://accounts.spotify.com/api/token', {
        method: 'POST', //Request Type
        body: formBody, //post body
        headers: {
        //Header Defination
        'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')),
        },
    })
    try{
        return await response.json()
    }catch (error){
        console.log(error)
    }
    
}

The above takes care of auth and getting refresh tokens, below takes care of searching for a track. To get 30 second previews there is a preview property in the return data for getTrack()

const apiPrefix = 'https://api.spotify.com/v1';

export default async ({
  offset,
  limit,
  q,
  token,
}) => {
  const uri = `${apiPrefix}/search?type=track&limit=${limit}&offset=${offset}&q=${encodeURIComponent(q)}`;
  console.log('search begin, uri =', uri, 'token =', token);
  const res = await fetch(uri, {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`,
    }
  });
  const json = await res.json();
  //console.log('search got json', json);

  if (!res.ok) {
    return [];
  }
  return json
  // const {
  //   tracks: {
  //     items,
  //   }
  // } = json;
  // // const items = json.tracks.items;
  // return items.map(item => ({
  //   id: item.id,
  //   title: item.name,
  //   imageUri: item.album.images
  //     ? item.album.images[0].url
  //     : undefined
  // }));
  console.log('search end');
};

export const getTrack = async(trackID, token) => {
  const uri = `${apiPrefix}/tracks/${trackID}?market=ES`;

  const res = await fetch(uri, {
    method: 'GET',
    headers: {
      // Accept: `application/json`,
      // Content-Type: `application/json`,
      Authorization: `Bearer ${token}`,
    }
  });
  const json = await res.json();
  //console.log('search got json', json);
  
  if (!res.ok) {
    return [];
  }
  return json
}