Wishal
Wishal

Reputation: 25

React won't render elements in map function

I'm trying to render elements from a map function however it does not seem to be working. I have tried to change the return but nothing seems to work.

class API extends Component {
  myTop10Artists() {
    Api.getMyTopArtists(function (err, data) {
      if (err) {
        console.error(err);
      } else {
        console.log(data.items);
        return data.items.map((artist) => {
          console.log("artist name " + artist.name);
          console.log("artist id " + artist.id);
          console.log("artist popularity " + artist.popularity);
          return (
            <div key={artist.id} className="card">
              <div key={artist.id} className="cardContent">
                <h3> {artist.name} </h3>{" "}
              </div>{" "}
            </div>
          );
        });
      }
    });
  }
  render() {
    return <div className="cardsWrap"> {this.myTop10Artists()} </div>;
  }
}

Upvotes: 1

Views: 1420

Answers (4)

Mohamed AbuElNasr
Mohamed AbuElNasr

Reputation: 1

1-use map function inside your return
2-use round braces instead of curly braces to surround your arrow function

return ({data.items.map((artist) => (
            <div key={artist.id} className="card">
              <div key={artist.id} className="cardContent">
                <h3> {artist.name} </h3>{" "}
              </div>{" "}
            </div>
       ))};
);
       

Upvotes: 0

Wakeel
Wakeel

Reputation: 5002

Store items in state and update it with the api response. This will cause your component to rerender.

Also, move your api call to component hook

componentDidMount(){
  Api.getMyTopArtists(function (err, data) {
      this.setState({
           items: data.items
       })
   }

Upvotes: 1

Sherif Wael
Sherif Wael

Reputation: 455

This won't work, because you are returning your data from a callback, instead you need to store using this.setState()the fetched data into your state and then display it.

class API extends Component {
  constructor(props){
    super(props);
    this.state = {
      data: null,
      error: null
    }
    this.myTop10Artists = this.myTop10Artists.bind(this);
  }
  
  componentDidMount(){
    this.myTop10Artists();
  }
  
  myTop10Artists() {
    Api.getMyTopArtists(function (err, data) {
      if (err) {
        this.setState({...this.state, error: err});
      } else {
        this.setState({error: null, data})
      }
    });
  }
  
  render() {
    const {error, data} = this.state;
    if(error){
      return <div>Error! Try again</div>
    }
    
    if(!data){
      return <div>Loading..</div>
    }
    
    return (
      <div>
         data.items.map((artist) => (
            <div key={artist.id} className="card">
              <div key={artist.id} className="cardContent">
                <h3> {artist.name} </h3>{" "}
              </div>{" "}
            </div>
        ))
      </div>
    )
  }
}

Upvotes: 1

Julian Kleine
Julian Kleine

Reputation: 1547

Just an idea of how to do approach this another way with hooks and functional components. Main issue in your code, as mentioned by others already, is the fact that the results are not returned by the callback or set to a state.

const MyTop10Artists = () => {
  const [artists, setArtists] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState();

  useEffect(() => {
    Api.getMyTopArtists((err, data) => {
      if (err) {
        console.error(err);
        setError(err);
        return;
      }
      setArtists(data.items);
      setIsLoading(false);
    });
  }, []);

  return (
    <>
      {isLoading && "Loading"}
      {error && error}
      {!isLoading && artists.length === 0 && "No artists"}
      {!isLoading &&
        artists.map((artist) => (
          <div key={artist.id} className="card">
            <div key={artist.id} className="cardContent">
              <h3>{artist.name}</h3>
            </div>
          </div>
        ))}
    </>
  );
};

const API = () => (
  <div className="cardsWrap">
    <MyTop10Artists />
  </div>
);

Upvotes: 1

Related Questions