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:
- Crypto Tracker
- Prices Checker
- Trading Bot
- Dashboard.
In this article, you'll learn how to build a Crypto Tracker using React.js for the User Interface (UI).
Prerequisites
- Basic understanding of JavaScript, ReactJs, and CSS
- Node.js and npm installed
- Familiarity with REST APIs
Installed the following:
- Reactjs either Create React App or Vite.js
- Axios
- React Router Dom
- Recharts
- TailwindCSS or Bootstrap (included in the code)
- Code Editor
Setting up the tracker’s components
- Clear out
App.jsx
file to have something like: This file will be handling all the routing. - Clear out
Index.css
andApp.css
- Create a folder inside
src
folder and name itComponent
. This will be where the display file for Coins’ details and the Search field will be stored. - Create two files inside
Component
and name themDisplay.jsx
andSearch.jsx
- Create another component under
src
folder and name itHomepage.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
useState
: This hook is used for adding state management to functional components. In the context ofHomepage.jsx
,useState
will be used to manage the state ofcoin
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;
CoinGecko API Endpoints
- 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.
- endpoint: https://api.coingecko.com/api/v3/coins/{id}
- 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.
- endpoint: https://api.coingecko.com/api/v3/coins/{id}/market_chart
- Search Queries: This endpoint allows you to search for coins, categories and markets listed on CoinGecko.
- endpoint: https://api.coingecko.com/api/v3/search
- 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👇🏽
const [trendingCoins, setTrendingCoins] = useState([]);
- This line initializes a state variable
trendingCoins
with an empty array.setTrendingCoins
is the function used to update this state. - The
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. - Inside
useEffect
, an asynchronous functionfetchData
is defined and immediately called. This function usesaxios.get
to make a GET request to the CoinGecko API to fetch trending coins. - If the request is successful, the response data (
response.data.coins
) is logged to the console and used to update thetrendingCoins
state withsetTrendingCoins
. - If there's an error during the fetch operation, it's caught in the catch block and logged to 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:
- A link (
<Link>
) that navigates to a detailed page for the coin. Theto
attribute of the link is dynamically set to/coin/${coin.item.id}
, wherecoin.item.id
is the unique identifier for each coin. - An image of the coin (
<img>
), wheresrc
is set tocoin.item.thumb
, representing the coin's thumbnail image URL, andalt
is set tocoin.item.name
, providing a text alternative for the image. - The coin's name (
<h1>
), is displayed in a large, bold font. - The coin's price (
<p>
), wherecoin.item.data.price.toFixed(3)
formats the price to three decimal places. This indicates thatcoin.item.data.price
is a numerical value representing the coin's current price. - The coin's market cap rank (
<p>
), is displayed usingcoin.item.market_cap_rank
. This is a numerical rank indicating the coin's position based on its market capitalization. -
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:
- Rechart package.
useParam
hooks from React Router Dom to access the URL parameters, specifically to get the ID of the cryptocurrency.- 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
- The response from the API contains price data as an array of
[timestamp, price]
pairs. - This data is mapped over to transform it into an array of objects with
Date
andPrice
properties, whereDate
is a formatted date string andPrice
is the cryptocurrency price. - The transformed data is then set to the
graphRes
state usingsetGraphRes
.
Rendering the chart
- The component returns JSX that renders an
AreaChart
component fromrecharts
. - The
AreaChart
is configured with a fixed width and height, and it's provided the data fromgraphRes
. - Inside the
AreaChart
, various components configure the appearance and behavior of the chart: CartesianGrid
adds a grid to the chart.XAxis
andYAxis
define the axes of the chart, withDate
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 toPrice
for plotting, along with stroke and fill colors.-
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 :
- Rechart Component by importing it
- useParams Hook.
- 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:
- Search Queries
- 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;
- State Management: It uses the
useState
hook to manage:
apiResponse
: Stores the response from the CoinGecko API.search
: Stores the current value of the search input field.
- 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. - 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 theapiResponse
state. If an error occurs, it's logged to the console. - Debounced Search: The
debounce
function is applied tohandleSearch
with a 500ms delay, creating a new functiondebouncedSearch
. This meanshandleSearch
will only be called if there's a 500ms pause in invokingdebouncedSearch
, effectively reducing the number of API calls during rapid typing. - useEffect Hook: React's
useEffect
hook is used to calldebouncedSearch
whenever thesearch
state changes. This means the API call will be made 500ms after the user stops typing. - Rendering: The component renders:
- An input field for the user to type their search query. The input's value is bound to the
search
state, and it updates thesearch
state on change. - A conditional block that checks if
apiResponse
is not null. If true, it maps overapiResponse.coins
and renders a list of coins. Each coin is wrapped in aLink
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🍾👏🏽
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
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.