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:
In this article, you'll learn how to build a Crypto Tracker using React.js for the User Interface (UI).
App.jsx
file to have something like: This file will be handling all the routing.Index.css
and App.css
src
folder and name it Component
. This will be where the display file for Coins’ details and the Search field will be stored.Component
and name them Display.jsx
and Search.jsx
src
folder and name it Homepage.jsx
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
In this tutorial, you will be making use of useState
and UseEffect
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.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;
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👇🏽
const [trendingCoins, setTrendingCoins] = useState([]);
trendingCoins
with an empty array. setTrendingCoins
is the function used to update this state.useEffect
hook is used to fetch data from an external API (https://api.coingecko.com/api/v3/search/trending
) when the component mounts. The empty dependency array []
means this effect runs once after the initial render.useEffect
, an asynchronous function fetchData
is defined and immediately called. This function uses axios.get
to make a GET request to the CoinGecko API to fetch trending coins.response.data.coins
) is logged to the console and used to update the trendingCoins
state with setTrendingCoins
.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;
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:
<Link>
) that navigates to a detailed page for the coin. The to
attribute of the link is dynamically set to /coin/${coin.item.id}
, where coin.item.id
is the unique identifier for each coin.<img>
), where src
is set to coin.item.thumb
, representing the coin's thumbnail image URL, and alt
is set to coin.item.name
, providing a text alternative for the image.<h1>
), is displayed in a large, bold font.<p>
), where coin.item.data.price.toFixed(3)
formats the price to three decimal places. This indicates that coin.item.data.price
is a numerical value representing the coin's current price.<p>
), is displayed using coin.item.market_cap_rank
. This is a numerical rank indicating the coin's position based on its market capitalization.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).
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:
useParam
hooks from React Router Dom to access the URL parameters, specifically to get the ID of the cryptocurrency.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
[timestamp, price]
pairs.Date
and Price
properties, where Date
is a formatted date string and Price
is the cryptocurrency price.graphRes
state using setGraphRes
.AreaChart
component from recharts
.AreaChart
is configured with a fixed width and height, and it's provided the data from graphRes
.AreaChart
, various components configure the appearance and behavior of the chart:CartesianGrid
adds a grid to the chart.XAxis
and YAxis
define the axes of the chart, with Date
being used as the data key for the X-axis.Tooltip
enables a tooltip that shows information about a data point when hovered.Area
defines the area chart itself, specifying that it should be a monotone type for smooth curves, and it sets the data key to Price
for plotting, along with stroke and fill colors.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 :
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
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 👇🏽
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:
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;
useState
hook to manage:apiResponse
: Stores the response from the CoinGecko API.search
: Stores the current value of the search input field.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.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.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.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.search
state, and it updates the search
state on change.apiResponse
is not null. If true, it maps over apiResponse.coins
and renders a list of coins. Each coin is wrapped in a Link
component for navigation, with the coin's name displayed as a link.After import the Search component into your Homepage.jsx
,
Congratulations, You have successfully built your own crypto Tracker🍾👏🏽
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.
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.