-2

I'm currently trying to take data from an API so I can use it on my page. I'm programming with React and I am trying to use useEffect with an async function.

Can someone please tell me why it breaks on a page refresh?

import React, { useEffect, useState } from 'react'
import axios from 'axios'
import './Cryptoinfo.css'

function Cryptoinfo() {
  const [coinprice, setCoinprice] = useState([])
  const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur`

  useEffect(() => {
    async function fetchData() {
      try {
        const result = await axios.get(url)
        setCoinprice(result.data.slice(0, 10))
        console.log(result)
      } catch (e) {
        console.error(e)
      }
    }
    fetchData()
  }, [url])

  return (
    <>
      <div className='crypto-info-container'>
        <div className='name-pic'>
          <h3 className='crypto-info-img'>O</h3>
          <h3 className='crypto-info-name'>Name</h3> //this should be coinprice[0].name but it breaks if i do that.
        </div>
        <h3 className='crypto-info-price'>Price</h3>
        <h3 className='crypto-info-mc'>Marketcap</h3>
        <h3 className='crypto-info-vol'>Volume (24hr)</h3>
        <h3 className='crypto-info-sup'>Circulating supply</h3>
      </div>
    </>
  )
}

export default Cryptoinfo
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • `coinprice[0]` won't have data before your data is fetched. So you'll be doing `undefined.name` which will throw an error – Nick Parsons Nov 13 '21 at 13:25
  • coinprice[0] is undefined at first because it takes a second to load data from API. You can handle this behavior by applying a check inside the JSX like: `{ if(coinprice.length > 0) return

    coinprice[0].id

    }`. It simply means when Data is set in state...Render it
    – kazmi066 Nov 13 '21 at 13:33

4 Answers4

0

On the first time this component renders, the value of coinprice is []. When u try to get .name from it, it will break because u can't get.name from undefined value.

coinPrice[0] = undefined

coinprice[0].name = Uncaught TypeError

Stephan Hovius
  • 391
  • 1
  • 6
0

you can try like this coinprice[0]?.name or you have to put condition before html start like this {coinprice && ( ---HTML--- )}; hope it will help you.

Dhaval Samani
  • 257
  • 2
  • 5
0

It was mentioned the issue is coinprice was undefined which is true so here is a ternary solution until the data is returned from the API:

  return (
    <>
      <div className="crypto-info-container">
        {coinprice.length === 0 || coinprice.length === undefined ? (
          <h3 className="crypto-info-img">Loading</h3>
        ) : (
          <>
            <div className="name-pic">
              <h3 className="crypto-info-img">O</h3>
              <h3 className="crypto-info-name">Name</h3> //this should be coinprice[0]?.name but it
              breaks if i do that.
            </div>
            <h3 className="crypto-info-price">Price</h3>
            <h3 className="crypto-info-mc">Marketcap</h3>
            <h3 className="crypto-info-vol">Volume (24hr)</h3>
            <h3 className="crypto-info-sup">Circulating supply</h3>
          </>
        )}
      </div>
    </>
  )

More about optional chaining so it's technically missing its just an option to get around the undefined.

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
0

Modify your code.

import React, { useEffect, useState } from "react";
import axios from "axios";

function Cryptowatch() {
  const [data, setData] = useState([]);
  const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&per_page=5`;

  useEffect(() => {
    async function fetchData() {
      try {
        const result = await axios.get(url);
        setData(result.data);
        console.log(data);
      } catch (e) {
        console.error(e);
      }
    }

    fetchData();
  }, []);
  const cryptos = data.map((cryp) => {
    return (
      <div className="crypto-info-container">
        <div className="name-pic">
          <img src={data.image} className="crypto-info-img"></img>
          <h3 className="crypto-info-name">{cryp.name}</h3>
        </div>
        <h3 className="crypto-info-price">{cryp.current_price}</h3>
        <h3 className="crypto-info-mc">{cryp.market_cap}</h3>
        <h3 className="crypto-info-vol">{cryp.total_volume}</h3>
        <h3 className="crypto-info-sup">{cryp.total_supply}</h3>
      </div>
    );
  });
  return <>{data && cryptos}</>;
}

export default Cryptowatch;

codesandbox link

Nishanth
  • 304
  • 3
  • 12