1

I'm trying to play with Coingecko API just to get better at React but I'm already stuck ahah

The general app is very simple for now, index is displaying cards of all tokens with ticker and price. And each card is clickable to go on a more detailed page.

App.js

import axios from "axios";
import React, { useEffect, useState } from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import SingleCoin from "./pages/SingleCoin";

function App() {
  const [coinsData, setCoinsData] = useState([]);

  useEffect(() => {
    axios
      .get(
        "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=1&sparkline=false&price_change_percentage=1h%2C24h%2C7d%2C14d%2C30d%2C200d%2C1y"
      )
      .then((res) => setCoinsData(res.data));
  }, []);

  const Home = () => {
    return (
      <>
        <h2>Home</h2>
        <div className="app">
          {coinsData.map((coin) => {
            return (
              <div className="coin-card" key={coin.id}>
                <h2>{coin.id}</h2>
                <p>
                  Ticker: <span className="symbol">{coin.symbol}</span>
                </p>
                <p>Prix: {coin.current_price} $</p>
                <Link to={`/pages/${coin.id}`}>Plus d'infos</Link>
              </div>
            );
          })}
        </div>
      </>
    );
  };

  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/pages/">Single Coin</Link>
            </li>
          </ul>
        </nav>

        <Routes>
          <Route path="/" element={<Home />} />
          <Route
            path="/pages/:id"
            element={<SingleCoin />}
            handler={coinsData.id}
          />
        </Routes>
      </div>
    </Router>
  );
}

export default App;

SingleCoin.jsx

import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
import SinglePrice from "../components/SinglePrice";

const SingleCoin = () => {
  const { id } = useParams();
  const [SingleCoin, setSingleCoin] = useState({});
  useEffect(() => {
    axios
      .get(
        `https://api.coingecko.com/api/v3/coins/${id}`
      )
      .then((res) => setSingleCoin(res.data));
  }, [id]);

  return (
    console.log(SingleCoin),
    <article>
        {/* <div className="img">
          <img src={SingleCoin.image.thumb} alt="logo" />
        </div> */}
      <h1>{SingleCoin.symbol}</h1>
      <p>{SingleCoin.coingecko_rank}</p>
      <p>{SingleCoin.market_data.current_price.usd}</p>
      {/* <SinglePrice /> */}
      <br />
    </article>
  );
};

When I write SingleCoin.market_data.current_price.usd for the first time, it works perfectly. But if I just go back to Home and go to the exact same token, it shows this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'current_price')

I don't understand why the first time it works ans then it bugs. I'm probably missing something with my weak logic ahah.

A big thanks in advance guys!

PS : Little update: I see that my SingleCoin const is empty when I refresh, even when I leave the page and come back. So I'm probably doing something wrong with my useEffect but I'm definitely too dumb to see it

Charly
  • 65
  • 4

1 Answers1

0

Ok, that's crazy how much it helps me to ask questions sometimes ahah.

I think I found the way (not sure it is the best way but it works)

I just add optional chaining operator to the price and it works :

<p>{SingleCoin?.market_data?.current_price?.usd}</p>

Not sure this is the best way to proceed but if it can helps others, here is a solution!

Charly
  • 65
  • 4