Search code examples
arraysreactjsjsxspotify

Iterating through array one at a time in react jsx


How do I iterate one index at a time in the array 'tracks' in react jsx. I want to be able to iterate and display just one track at a time in the array, and go to the next track (index) on the click of a button that'll be labeled 'Next', also go back to previous index when clicking the button 'Previous'.

  constructor(props){
     super(props);
     this.state=({
        year: (props.location.state && props.location.state.year) || '',
        all_tracks: {tracks:[]},
        currentTrack: 0,
     });
  }
  onClickNext(){ //Next button
      //Nothing done here yet
  }
  onClickPrev(){ //Previous button
      //Nothing done here yet
  }
  render(){
    const {
      currentTrack,
      all_tracks: { tracks }
    } = this.state;
    return (
        window.addEventListener('DOMContentLoaded', (event) => { 
            this.gettingTracks() //Have tracks load immediately
        }),
       <div id = "song"> //THIS PART
              <iframe id="track" src={tracks[currentTrack]
                           ? "https://open.spotify.com/embed/track/"+tracks[currentTrack].id
                           : "Song N/A"} ></iframe>
       </div>
       <div>
            <button id="nextBtn"> Next </button>
       </div>
       <div>
            <button id="prevBtn"> Previous </button>
       </div>
     );
  }

Here is where I populate the tracks array

    gettingTracks(){
    // store the current promise in case we need to abort it
    if (prev !== null) {
        prev.abort();
    }
    // store the current promise in case we need to abort it
    prev = spotifyApi.searchTracks('genre: pop year:' + this.state.year, {limit: 20, offset:1});
    prev.then((data) => {
        this.setState({
          all_tracks: { 
              tracks: data.tracks.items
            }
        })
        prev = null;
    }, function(err) {
        console.error(err);
    });
}

Solution

  • You can store the index of the current track as a state variable. And instead of iterating over the tracks to display them, you can just simply display the current track.

    Here is a simple example,

    import React from "react";
    
    export default class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          all_tracks: {
            tracks: []
          },
          currentTrack: 0
        };
    
        this.onClickNext = this.onClickNext.bind(this);
        this.onClickPrev = this.onClickPrev.bind(this);
      }
    
      componentDidMount() {
          // fetch the data  from the Spotify API and update this.state.all_tracks.tracks
    
      }
    
      onClickNext() {
        //Next button
        this.setState(prevState => {
          if (this.state.currentTrack === this.state.all_tracks.tracks.length - 1) {
            return;
          }
    
          return {
            ...prevState,
            currentTrack: prevState.currentTrack + 1
          };
        });
      }
      onClickPrev() {
        //Previous button
        this.setState(prevState => {
          if (this.state.currentTrack === 0) {
            return;
          }
    
          return { ...prevState, currentTrack: prevState.currentTrack - 1 };
        });
      }
      render() {
        const {
          currentTrack,
          all_tracks: { tracks }
        } = this.state;
    
        // before rendering tracks[currentTrack].name check if tracks[currentTrack] exist
    
        return (
          <>
            <div>
              <h3>Current Track</h3>
              <h4>
               {
                 tracks[currentTrack] 
                    ? tracks[currentTrack].name 
                    : 'track does not exist'
               }
              </h4>
            </div>
            <div>
              <button id="nextBtn" onClick={this.onClickNext}>
                Next
              </button>
            </div>
            <div>
              <button id="prevBtn" onClick={this.onClickPrev}>
                Previous
              </button>
            </div>
          </>
        );
      }
    }
    

    Check the codesandbox for demo