0

I am trying to create a table with different crypto currencies and their values using react and coingecko api. I am new to api and api calls and every time i make a call i keep getting TypeError: Cannot read properties of undefined (reading 'map').

     const [crypData, setCrypData] = useState([]);
    
      const apiGet = () =>{
        fetch('https://api.coingecko.com/api/v3/exchange_rates') 
        .then(response => {
            if(response.ok){
                return response.json()
            }
             throw response;
        })
        .then(res => {
            
            console.log(res); 
            setCrypData(res.data); 
            console.log("crypData"); 
    
           });
        };
    
    
      useEffect(() => { 
        apiGet();
      },[])
     
    return ( 
            <>
            {crypData.map(item =>
                <tr > 
                    <td scope="row">{item.rates.btc.name} </td> 
                    <td>{item.rates.btc.unit} </td>
                    <td>{item.rates.btc.value} </td>  
                    <td>
                        {item.rates.btc.type} 
                        <button type="button"></button>
                    </td>
                </tr>
            )} 
            </>
         );
    }
     
    export default DataTables;

When i change the response i am still getting this TypeError: crypData.map is not a function


       .then(res => {
           
           console.log(res); 
           setCrypData(res); 
           console.log("crypData"); 
   
          });
General Grievance
  • 4,555
  • 31
  • 31
  • 45
  • What does this log to the console?: `console.log(res);` When I make a request to that API, I don't see a `data` property. Or any array at all. – David Sep 20 '21 at 11:40
  • this logs to show response from fetch('https://api.coingecko.com/api/v3/exchange_rates') without changing to list – Paul Barasa Sep 20 '21 at 11:42
  • Could be that it's a lifecycle issue, before calling the api or before it sets the value to the state the component wants to render. When you used the second part did the data printed to the console seem ok? – Noam Yizraeli Sep 20 '21 at 11:42
  • @PaulBarasa: Where specifically in that response are you seeing a `data` property? Or any kind of array on which to call `.map()`? – David Sep 20 '21 at 11:43
  • 1
    yes the data seems okay until i try to add to setCrypData(res.data); – Paul Barasa Sep 20 '21 at 11:44

1 Answers1

0

A critical part of your debugging is to examine the actual response from the server. Edited for brevity but structurally the same, that response is:

{
   "rates":{
      "btc":{
         "name":"Bitcoin",
         "unit":"BTC",
         "value":1.0,
         "type":"crypto"
      },
      "eth":{
         "name":"Ether",
         "unit":"ETH",
         "value":14.367,
         "type":"crypto"
      },
      "ltc":{
         "name":"Litecoin",
         "unit":"LTC",
         "value":277.933,
         "type":"crypto"
      }
   }
}

As you can see, there is no data property at the root of the object. So res.data is undefined. And you can't call .map() on undefined. Additionally, there is no array, only an object. And you can't call .map() on an object because it's not a function on objects.

Your res object in the API result has a single property called rates, which is an object containing many properties, all of which have the same object structure. If you want to .map() over those properties then you're first going to need to convert them to an array. Then you would pass that array to setCrypData() to update your state.

David
  • 208,112
  • 36
  • 198
  • 279