CoinGecko is a comprehensive cryptocurrency data platform that provides real-time and historical data on thousands of cryptocurrencies. It offers a market-tracking website and app for digital currencies. CoinGecko collects data to rank the potential of each coin, benchmarking digital currencies like Bitcoin, Ethereum, and over 6,000 other cryptocurrencies. In short, think of CoinGecko as a library that provides information on various cryptocurrencies. It offers a wide range of information, including price, volume, market capitalization, and more, as seen below:





As CoinGecko offers these services, it also extends its capabilities to developers and organizations through its Application Programming Interface (API), allowing them to use the vast amount of available data. This API provides access to real-time and historical data, enabling the creation of applications that can track cryptocurrency prices, analyze market trends, and more.


CoinGecko's API offers features and endpoints like Market Data, Historical Data, Exchange Data, Global Data, Trending Coins, NFTs Data, and more.


Some of the applications that can be built with CoinGecko's API include:

  1. Crypto Tracker
  2. Prices Checker
  3. Trading Bot
  4. Dashboard.


In this article, you'll learn how to build a Crypto Tracker using React.js for the User Interface (UI).

Prerequisites

Installed the following:

  1. Reactjs either Create React App or Vite.js
  2. Axios
  3. React Router Dom
  4. Recharts
  5. TailwindCSS or Bootstrap (included in the code)
  6. Code Editor


Setting up the tracker’s components


  1. Clear out App.jsx file to have something like: This file will be handling all the routing.
  2. Clear out Index.css and App.css
  3. Create a folder inside src folder and name it Component. This will be where the display file for Coins’ details and the Search field will be stored.
  4. Create two files inside Component and name them Display.jsx and Search.jsx


  1. Create another component under src folder and name it Homepage.jsx

Displaying Content

To display these components, you will be using the React Router Dom functions such BrowserRouter and Routes and importing them into App.jsx in this manner 👇🏽


import './App.css' import DisplayCoin from './Component/Display

 import Homepage from './Homepage 

import { BrowserRouter, Route, Routes} from 'react-router-dom' 

function App() { 

return ( 

     <BrowserRouter>

       <Routes>

         <Route path="/" element={<Homepage />} />

         <Route path="/coin/:id" element={<DisplayCoin />} /> //'/coin/:id' to display the details of coin using its id

       </Routes>

      </BrowserRouter> 
       ) 
} 

export default App


Fetching Data from CoinGecko API

React Hooks (useState, useEffect)

In this tutorial, you will be making use of useState and UseEffect

  1. useState: This hook is used for adding state management to functional components. In the context of Homepage.jsx, useState will be used to manage the state of coin or any other data that needs to be displayed or updated in the UI. For example, you will fetch coin data from an API and store it in a state variable so that it can be displayed dynamically in the component.

  2. useEffect: This hook is used for performing side effects in functional components. Side effects could be data fetching, subscriptions, or manually changing the DOM in React components. In this case, useEffect will be used to fetch the coin data from an API when the component mounts. It ensures that the data fetching logic is kept separate from the UI logic, and it can also handle re-fetching data if any dependencies change.


Having this understanding, Open Homepage.jsx and import useState and useEffect into the file in this manner👇🏽


import React, { useState, useEffect } from 'react'

const Homepage = () => {

return (

<div> Crypto Tracker </div>

) }

export default Homepage;


CoinGecko API Endpoints

  1. Coin Data by ID: This endpoint allows you to query all the coin data of a coin (name, price, market .... including exchange tickers) on the CoinGecko coin page based on a particular coin ID.
  2. endpoint: https://api.coingecko.com/api/v3/coins/{id}
  3. Coin historical Chart Data by ID: This endpoint allows you to get the historical chart data of a coin including time in UNIX, price, market cap and 24hrs volume based on a particular coin id.
  4. endpoint: https://api.coingecko.com/api/v3/coins/{id}/market_chart
  5. Search Queries: This endpoint allows you to search for coins, categories and markets listed on CoinGecko.
  6. endpoint: https://api.coingecko.com/api/v3/search
  7. Trending Search List: This endpoint allows you to query trending search coins, nfts and categories on CoinGecko in the last 24 hours.endpoint: https://api.coingecko.com/api/v3/search/trending


Fetching Trending Coin

To fetch the trending coin, we will be making using axios, useEffect, useState and Trending Search list endpoint.


         
    import React, { useState, useEffect } from 'react'

import axios from 'axios'

import { Link } from 'react-router-dom'

const Homepage = () => {

const [trendingCoins, setTrendingCoins] = useState([]);

useEffect(() => 
{ const fetchData = 
async () => { try 
{ const response = await axios.get('https://api.coingecko.com/api/v3/search/trending');
     console.log(response.data);

    } catch (error) {
        console.error(error);
    }
}
fetchData();
}, []);

return ( <div> Crypto Tracker </div> )

}

export default Homepage;



You will see the response in the console👇🏽




From the above picture, you can see the list of Trending Coins, Categories, and NFTs. In this case, you only need the trending coins’ details. To do this, you just need to add setTrendingCoins(response.data.coins);


     import React, { useState, useEffect } from 'react'

import axios from 'axios'

import { Link } from 'react-router-dom'

const Homepage = () => {

const [trendingCoins, setTrendingCoins] = useState([]);

useEffect(() => { const fetchData = async () => { try { const response = await axios.get('https://api.coingecko.com/api/v3/search/trending'); console.log(response.data);  

setTrendingCoins(response.data.coins);

    } catch (error) {
        console.error(error);
    }
}
fetchData();
}, []);

return ( <div> Crypto Tracker </div> )

}

export default Homepage;

Trending Coin UI


import React, { useEffect, useState } from 'react'

import axios from 'axios'

import { Link } from 'react-router-dom';

const Homepage = () => { const [trendingCoins, setTrendingCoins] = useState([]);

useEffect(() => { const fetchData = async () => { try { const response = await axios.get('https://api.coingecko.com/api/v3/search/trending'); console.log(response.data); setTrendingCoins(response.data.coins); } catch (error) { console.error(error); } } fetchData(); }, []);

return ( <div className=''>

<h1 className="text-2xl font-bold text-center tracking-wider">TRENDING COINS</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4 pl-10">
    {trendingCoins.map((coin, index) => (
    <Link to={`/coin/${coin.item.id}`} key={index} className="max-w-sm rounded overflow-hidden shadow-lg p-4 hover:bg-gray-900 hover:shadow-2xl transition duration-300 ease-in-out">
      <div key={index} className="max-w-sm rounded overflow-hidden shadow-lg p-4">
        <img src={coin.item.thumb} alt={coin.item.name} className="w-20 h-20 mx-auto" />
        <div className='flex flex-col justify-center items-center'>
        <h1 className="text-2xl font-bold">{coin.item.name}</h1>
        <p className="text-gray-600">Price: ${coin.item.data.price.toFixed(3)}</p>
        <p className="text-gray-600">Market Cap Rank: {coin.item.market_cap_rank}</p>
        </div>
      </div>
    </Link>
    ))}
</div> 
</div>

) }

export default Homepage


The trendingCoins state variable, which now holds the API response data, is mapped over to dynamically generate a list of coin elements. For each coin in trendingCoins, the following information is displayed:


Styling and Layout

The coins are displayed in a responsive grid layout, with styling applied for aesthetics (e.g., rounded corners, shadow, hover effects) and responsiveness (e.g., different column counts for different screen sizes).



Coin Chart Data with Price and TimeStamp

This is the graphical illustration that shows the changes in prices within one day. To do this Create another file and name Rechart.jsx inside the Component.

You will be making use of the:

  1. Rechart package.
  2. useParam hooks from React Router Dom to access the URL parameters, specifically to get the ID of the cryptocurrency.
  3. Coin historical Chart Data by ID endpoint.


Inside the file add the following 👇🏽


    import React, { useEffect, useState} from 'react' 
import axios from 'axios' import { useParams } from 'react-router-dom'; 
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts';

const Rechart = () => { 
const params = useParams(); 
const [graphRes, setGraphRes] = useState([]);

useEffect(() => { const fetchData = async () => {


try {

        const response = await axios.get(`https://api.coingecko.com/api/v3/coins/${params.id}/market_chart?vs_currency=usd&days=1`);
        
           setGraphRes(response.data.prices.map((item) => {
            const [timestamp, p] = item;

            const date = new Date(timestamp).toLocaleDateString('en-us')

            return {
                Date: date,
                Price: p,
            };
        }));
    } catch (error) {
        console.error(error);
    }
};

fetchData();
}, []);

return ( <div> <AreaChart
 width={750}
    height={400}
    data={graphRes}
    margin={{
        top: 10,
        right: 30,
        left: 0,
        bottom: 0,
    }}
>

    <CartesianGrid strokeDasharray="3 3" />
    <XAxis dataKey="Date"/>
    <YAxis />
    <Tooltip />
    <Area type="monotone" dataKey="Price" stroke="#8884d8" fill="#8884d8" />
</AreaChart>


</div>

) }

export default Rechart


Data Processing

Rendering the chart


Coin Details UI

Recall the Display.jsx component you created at the start of this tutorial; this is where the coin details including coin chart data will be shown when a user clicks on any trending coin or searches for a specific coin.


In this component, you will be making use of :

  1. Rechart Component by importing it
  2. useParams Hook.
  3. Coin Data by ID endpoint


import React, { useEffect, useState} from 'react' 
import axios from 'axios' import { useParams } from 'react-router-dom'; 
import Rechart from './Rechart';

const Display = () => { const params = useParams(); 
const [apiResponse, setApiResponse] = useState([]);

useEffect(() => { const fetchData = 
async () => { try 
{ const apiResponse = await axios.get(https://api.coingecko.com/api/v3/coins/${params.id}?localization=false); 
console.log(apiResponse); 
setApiResponse(apiResponse) 
} catch (error) { 
console.error(error); 
}

};

fetchData(); }, []); 
return ( <div> {apiResponse.data && 
( <div className=" max-w-screen-md mx-auto rounded-lg overflow-hidden shadow-lg p-6 bg-white"> 
<h1 className="text-2xl font-bold text-gray-800 mb-4 text-center">{apiResponse.data.name}</h1> 
<img src={apiResponse.data.image.small} alt={apiResponse.data.name} className="w-80 ml-20 lg:ml-52 mb-4 rounded-lg shadow" /> 
<Rechart/> 
<h2 className="font-bold text-lg text-gray-800 mb-2 text-center tracking-widest">DETAILs</h2> 
<div className=' leading-12 '> 
<p className="text-gray-600 mb-10 flex justify-between border-b-2">Currency <span className="font-semibold">{apiResponse.data.symbol}</span></p> 
<p className="text-gray-600 mb-10 flex justify-between border-b-2">Market Cap Rank <span className="font-semibold">{apiResponse.data.market_cap_rank}</span></p> 
<p className="text-gray-600 mb-10 flex justify-between border-b-2">Market Cap <span className="font-semibold">${apiResponse.data.market_data.market_cap.usd}</span></p> 
<p className="text-gray-600 mb-10 flex justify-between border-b-2">Total Supply <span className="font-medium">{apiResponse.data.market_data.total_supply}</span></p> 
<p className="text-gray-600 mb-10 flex justify-between border-b-2">Circulating Supply <span className="font-medium">{apiResponse.data.market_data.circulating_supply}</span></p> 
<p className="text-gray-600 flex justify-between border-b-2">Max Supply <span className="font-medium">{apiResponse.data.market_data.max_supply}</span></p> 
</div> 
</div> 
)
} 
</div> 
) }

export default Display


Fetching Coin Details

Makes asynchronous GET request to fetch detailed information about the cryptocurrency using Coin Data by ID endpoint. The URL includes a query parameter for disabling localization and a demo API key.


So when the users click on any coin, they should see a UI like this 👇🏽

Search field

Here, the user will be able to search for any cryptocurrencies and there will be list of cryptocurrencies related to the inputed text. For this functionality, you will be using:

  1. Search Queries
  2. Javascript Debounce functionality


Add the following code to the file👇🏽

import React, { useEffect, useState } from 'react'; 
import axios from 'axios'; 
import { Link } from 'react-router-dom';

const Search = () => { 
const [apiResponse, setApiResponse] = useState(null); 
const [search, setSearch] = useState('');

const debounce = (func, delay) => { 
let inDebounce; 
return function() 
{ const context = this; 
const args = arguments; 
clearTimeout(inDebounce); 
inDebounce = setTimeout(() => func.apply(context, args), delay); 
}; };

const handleSearch = async () => 
{ if (!search) 
 { setApiResponse(null); 
return; 
} try { 
const response = await axios.get(https://api.coingecko.com/api/v3/search?query=${search}); 
console.log(response.data); 
setApiResponse(response.data); 
} catch (error) { 
console.error('Error:', error); 
} 
};

const debouncedSearch = debounce(handleSearch, 500);

useEffect(() => { debouncedSearch(); }, [search]);

return ( 
<div className="p-4"> 
<input type="text" value={search} placeholder="Search for a coin" 
onChange={(e) => setSearch(e.target.value)} 
className="w-full h-12 my-4 p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" /> 
{apiResponse && ( 
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4"> 
{apiResponse.coins.map((coin, index) => 
( <div key={index} className="max-w-sm rounded overflow-hidden shadow-lg p-4"> 
<Link to={/coin/${coin.id}} className="text-blue-500 hover:text-blue-700">{coin.name}</Link> 
</div> )
)} 
</div> 
)} 
</div> 
);

};

export default Search;


  1. State Management: It uses the useState hook to manage:


  1. Debounce Function: A debounce function is defined to limit the rate at which a function (handleSearch) is executed. This is use to optimizing performance and reducing the number of API calls made while typing in the search input.
  2. handleSearch Function: This asynchronous function is triggered to call the CoinGecko API. It checks if the search state is not empty, then makes a GET request to the CoinGecko API with the search query. The response is logged to the console and stored in the apiResponse state. If an error occurs, it's logged to the console.
  3. Debounced Search: The debounce function is applied to handleSearch with a 500ms delay, creating a new function debouncedSearch. This means handleSearch will only be called if there's a 500ms pause in invoking debouncedSearch, effectively reducing the number of API calls during rapid typing.
  4. useEffect Hook: React's useEffect hook is used to call debouncedSearch whenever the search state changes. This means the API call will be made 500ms after the user stops typing.
  5. Rendering: The component renders:



After import the Search component into your Homepage.jsx,



Congratulations, You have successfully built your own crypto Tracker🍾👏🏽

Conclusion

In this article, you learned about the CoinGecko API, including its key features and endpoints, and how to use Axios to fetch data. You also explored examples of applications you can build with the API and followed a step-by-step guide to creating a complete application.

Further Resources

CoinGecko Documentation

Building a crypto price app in React

More features in the Crypto Tracker


If you find this article helpful, let me know in the comment section, like✅, share 🛂 and follow 🚶🏽‍♂️for more.