Home > Enterprise >  Trying to iterate over a nested object from an API and return the data into my react component
Trying to iterate over a nested object from an API and return the data into my react component

Time:10-31

I have a nested object which is a little complicated since it has numeric value as ID of each entry.

"coins":
0:{...}29 items
1:{...}29 items
2:{...}29 items
3:{...}29 items
4:{...}29 items

This is my code, this is not working for me. Console log is returning data but the UI component is not being rendered

import React, { useState, useEffect } from "react";
import "./Homepage.css";
import CryptoCard from "../Card/Card";
import axios from "axios";

const Homepage = () => {
  const [coinData, setCoinData] = useState([], () => {
    const localData = localStorage.getItem("coinData");
    return localData ? JSON.parse(localData) : [];
  });

  useEffect(() => {
    const options = {
      method: "GET",
      url: "https://coinranking1.p.rapidapi.com/coins",
      headers: {
        "x-rapidapi-host": "coinranking1.p.rapidapi.com",
        "x-rapidapi-key": "API_KEY",
      },
    };

    axios
      .request(options)
      .then((response) => {
        setCoinData(response.data.data.coins);
        // persist in localStorage
        localStorage.setItem(
          "coinData",
          JSON.stringify(response.data.data.coins)
        );
      })
      .catch((error) => {
        console.error(error);
      });
  }, []);

  console.log("Coins names");
  coinData.forEach(function (coin) {
    console.log(coin.name);
  });

  const i = 0;
  return (
    <div className="homepage">
      <div className="heading">
        <h1>Discover</h1>
        <hr className="line" />
      </div>
      <div className="cards-container">
        {coinData?.forEach(function (coin) {
          <CryptoCard
            name={coin.name}
            coinUrl={coin.websiteUrl}
            duration="4 minutes ago"
            symbol={coin.symbol}
            rank={coin.rank}
            exchanges={coin.numberOfExchanges}
            price={coin.price}
          />;
        })}
        {/* <CryptoCard
          name={coinData[0]?.name}
          coinUrl={coinData[0]?.websiteUrl}
          duration="4 minutes ago"
          symbol={coinData[0]?.symbol}
          rank={coinData[0]?.rank}
          exchanges={coinData[0]?.numberOfExchanges}
          price={coinData[0]?.price}
        /> */}
      </div>
    </div>
  );
};

export default Homepage;

I need to iterate over this and return the data from each entry into my React component and I can not figure out how to iterate over them without a loop. Using loop does not work either for me.

CodePudding user response:

In react you don't have to use forEach. Instead you have to use .map which is easy, declarative and do not mutate the original Array. With forEach if you alter some member of the coin value inside the loop, or even in the CryptoCard component, you are mutating the original array, which means mutate the react state, that's not allowed. But for this to work, please make sure to console log the coinData variable and check if it contains the value you expect.

        {coinData?.forEach(function (coin) {
          <CryptoCard
            name={coin.name}
            coinUrl={coin.websiteUrl}
            duration="4 minutes ago"
            symbol={coin.symbol}
            rank={coin.rank}
            exchanges={coin.numberOfExchanges}
            price={coin.price}
          />;
        })}

should be

        {(coinData|| []).map(coin => (
          <CryptoCard
            name={coin.name}
            coinUrl={coin.websiteUrl}
            duration="4 minutes ago"
            symbol={coin.symbol}
            rank={coin.rank}
            exchanges={coin.numberOfExchanges}
            price={coin.price}
          />;
        ))}

CodePudding user response:

You can do as follows:

{coinData?.map((coin) =>
    <CryptoCard
      name={coin.name}
      coinUrl={coin.websiteUrl}
      duration="4 minutes ago"
      symbol={coin.symbol}
      rank={coin.rank}
      exchanges={coin.numberOfExchanges}
      price={coin.price}
    />;
)}

.map will then return a list of your CryptoCard component.

CodePudding user response:

If the console.log statements are printing the intended values properly and the following snippet is not working,

<div className="cards-container">
  {coinData?.forEach(function (coin) {
    <CryptoCard
      name={coin.name}
      coinUrl={coin.websiteUrl}
      duration="4 minutes ago"
      symbol={coin.symbol}
      rank={coin.rank}
      exchanges={coin.numberOfExchanges}
      price={coin.price}
    />;
 })}
</div>

It might be because you are not returning anything from inside the function inside the forEach loop. Try adding return before the component inside the function, like so

{coinData?.forEach(function (coin) {
  return (
    <CryptoCard
      name={coin.name}
      coinUrl={coin.websiteUrl}
      duration="4 minutes ago"
      symbol={coin.symbol}
      rank={coin.rank}
      exchanges={coin.numberOfExchanges}
      price={coin.price}
    />;
  )
})}
  • Related