Search code examples
restreact-nativespotify

How can I render fetched information from a REST API in React Native?


I'm developing a screen which fetches Spotify playlists of a particular category, and prints the playlist information (and then allows the user to play them). I'm currently just trying to print the names of the playlists, but I'm getting an error. The playlists are being fetched just fine, as I can see in my console, though I'm struggling to render those details onto the screen.

This is my code:

import React, { Component } from 'react'
import { StyleSheet, SafeAreaView, ActivityIndicator, View, Text, Image} from 'react-native';
import * as Font from 'expo-font';
import styled from 'styled-components';
import { Ionicons } from '@expo/vector-icons';
import dimensions from '../components/ScreenSize';
import colours from '../components/Colours';
import { Audio } from 'expo-av';
import { FlatList, TouchableHighlight } from 'react-native-gesture-handler';

const client_id = {Client_ID}
const client_secret = {Client_Secret}

const item = ({item}) => (
    <View>
        <TouchableHighlight onPress={() => this.fetchTracks(item.id)}>
            <View>
                <Text {{uri:item.name}}/>
            </View>
        </TouchableHighlight>
    </View>
)

export default class HomeScreen extends React.Component {
    state={
      fontsLoaded:false,
    }
    async componentDidMount() {
      await Font.loadAsync({
        'montserrat-regular': require('../assets/fonts/Montserrat/Montserrat-Regular.ttf'),
        'montserrat-light': require('../assets/fonts/Montserrat/Montserrat-Light.ttf'),
        'montserrat-semibold': require('../assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
        'montserrat-bold': require('../assets/fonts/Montserrat/Montserrat-Bold.ttf'),
      }
      ).then(() => this.setState({ fontsLoaded:true}))
      this.getToken();
      this.setAudio();

    }

    constructor (props) {
        super(props)
        this.playbackInstance=null;
        this.state = {
            playing:false,
            token: '',
            DATA:[],
        };
    }

    setAudio=() => {
        Audio.setAudioModeAsync({
            allowsRecordingIOS:false,
            interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
            playsInSilentModeIOS: true,
            shouldDuckAndroid: true,
            interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
            playThroughEarpieceAndroid: false,
        });
    }

    componentDidCatch(error, info)
    {
        console.log(error, info.componentStack);
    }

    getToken = async() =>
    {
        try
        {
            const getspotifytoken = await fetch("https://accounts.spotify.com/api/token",
            {
                method:'POST',
                body: `grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            });

            const spotifytoken = await getspotifytoken.json();
            this.setState({
                token: spotifytoken.access_token
            });

            console.log(this.state.token);
        }
        catch(err)
        {
            console.log("Error fetching data ", err);
        }
    }

    search = async () => {
        try
        {
            const query = "mood"
            console.log('Searching: ', query)
            const spotifyApiCall = await fetch(`https://api.spotify.com/v1/browse/categories/${query}/playlists?`, {
                headers: {
                    Accept: 'application/json',
                    Authorization: `Bearer ${this.state.token}`,
                    "Content-Type":'application/json'
                }
            })
            const spotify = await spotifyApiCall.json();
            console.log("Items ", spotify);

            this.setState({
                DATA: spotify.playlists.items,
            })
        }
        catch (err)
        {
            console.log("Error fetching data ", err);
        }
    }

    fetchTracks = async (playlistId) => {
        console.log('Playlist ', playlistId)
        try
        {
            const getplaylist = await fetch(`https://api.spotify.com/v1.playlist/${playlistId}`,
            {
                method:'GET',
                headers: {
                    Accept:"application/json",
                    Authorization:`Bearer ${this.state.token}`,
                    "Content-Type":"application/json"
                }
            });

            const playlist = await getplaylist.json();
            console.log('music ', playlist.tracks.items[0].preview_url);
        }

        catch (err)
        {
            console.log("Error fetching data ", err);
        }
    }

    async _loadNewPlaybackInstance(playing, track) {
        if(this.playbackInstance != null)
        {
            await this.playbackInstance.unloadAsync();
            this.playbackInstance.setOnPlaybackStatusUpdate(null);
            this.playbackInstance = null;
        }

        const source = {uri: track};
        const initialStatus = {
            shouldPlay: true,
            rate: 1.0,
            shouldCorrectPitch: true,
            volume: 1.0,
            isMuted: false
        };
        const {sound, status} = await Audio.Sound.createAsync(
            source.initialStatus);
            this.playbackInstance=sound;
            this.playbackInstance.setIsLoopingAsync(false);
            this.playbackInstance.playAsync();

        if (this.state.selected === playlistId) {
            console.log("Playing, so stop");
            this.setState({selected:null});
            this.playbackInstance.pauseAsync();
            return;
        }

        this.setState({ selected:playlistId});
        this._loadNewPlaybackInstance(true, playlist.tracks.items[0].preview_url);
    }

    render() { 
      if(!this.state.fontsLoaded ) {
        return null
      }
      return (
        <Container>
          <Titlebar>
            <Title>Music</Title>
          </Titlebar>
          <HeaderBar2>
            <TouchableHighlight onPress={() => this.search()}> 
              <Header2>Playlists for your Mood</Header2>
            </TouchableHighlight>
          </HeaderBar2>
          <View>

              <FlatList
              data = {this.state.DATA}
              renderItem={item}
              keyExtractor = {item.id}
              numColumns={2}
              extraData = {this.state}
              />
          </View>
        </Container>
      );
    }
  }

And the error is: Unexpected token, expected '...' (18:23) which is in reference to the line which reads <Text {{uri:item.name}}/>

I've also tried <Text {{item.name}}/>, as well as a few other alternatives, but I can't quite figure it out.

Thank you for reading, I'd really appreciate any help!


Solution

  • The thing you are doing wrong is you can not use Text like you are using above, check with this:

    replace

     <Text {{uri:item.name}}/>
    

    to

    <Text>{item.name}</Text>
    

    Hope this helps!