Search code examples
javascriptreactjswebweb-applicationsspotify

Error I'm getting with React: If you meant to render a collection of children, use an array instead


So what I'm trying to do is get all the playlists from a user, which is working as I can see it when I console.log it. But I'm getting an error regarding to use an array to render the collection of children, for the playlist variable in getAll because that's where I'm trying to store it. I'm very new to react and javascript so I'm sure it's a bonehead error.

 class App extends Component {
  constructor(){
    super();
    var list = new Array();
    const params = this.getHashParams(); //tokens saved here
    const token = params.access_token;
    if (token) {
      spotifyApi.setAccessToken(token);
    }
    this.state = {
      loggedIn: token ? true : false,
      nowPlaying: { name: ' Not Checked', albumArt: '', albumName: ' Nobody'},
      getAll: {playlists: []}
    };
    this.getNowPlaying = this.getNowPlaying.bind(this);
    this.getPlaylists = this.getPlaylists.bind(this);
  }

  getHashParams() { //uses authenticated users refresh and access token
    var hashParams = {};
    var e, r = /([^&;=]+)=?([^&;]*)/g,
        q = window.location.hash.substring(1);
    e = r.exec(q)
    while (e) {
       hashParams[e[1]] = decodeURIComponent(e[2]);
       e = r.exec(q);
    }
    return hashParams;
  }

  getNowPlaying(){
        spotifyApi.getMyCurrentPlaybackState()
          .then((response) => {
            this.setState({
              nowPlaying: { 
                  name: response.item.name, 
                  albumArt: response.item.album.images[0].url,
                  albumName: response.item.album.name
                }
            });
          }) 
    }


  getPlaylists(){
    spotifyApi.getUserPlaylists()
      .then((response) => {
        console.log(response.items)
        this.setState({
          getAll: { 
            playlists: response.items
           }
        });
      })  
  }

  render() {
    return (
      <div className="App">
            <a href='http://localhost:8888' > 
                <button> Logout </button> 
            </a>
            <div>
                Now Playing: 
                { this.state.nowPlaying.name }
            </div>
            <div>
                Album: 
                { this.state.nowPlaying.albumName }
            </div>
            <div>
                <img src={this.state.nowPlaying.albumArt} style={{ height: 150 }} />
            </div>
           <ul>
            {           
                this.state.getAll.map((playlist, index) => (
                <li key={index}> { playlist }</li>
                ))
            }
            </ul>
            {
                <button onClick={() => this.getPlaylists()}>
                    Check Playlists
                </button>
            }

            { 
                this.state.loggedIn &&
                <button onClick={() => this.getNowPlaying()}>
                    Check Now Playing
                </button> 
            }
      </div>
    );
  }
}

export default App;

Solution

  • React won't work that way. You can do like this

    render() {
     return (
       <>
         All playlists:
       <ul>
         {
            this.state.getAll.playlist.map((playlist, index) => (
              <li key={index}> { playlist }</li>
            ))
         }
       </ul>
        <button onClick={() => this.getPlaylists()}>
             Check Playlists
         </button>
     </>
     )
    }
    

    Also, you need to bind all your functions in constructor or use arrow functions.

    this.getNowPlaying = this.getNowPlaying.bind(this);