Climate change is a critical global issue, with carbon dioxide (CO₂) emissions playing a significant role in driving global warming. To better understand CO₂ emission trends, we can utilize data from the World Bank Data API and visualize it for clearer insights. This article will walk you through building a CO₂ emission chart using React and CanvasJS. This chart will pull data from the World Bank API based on the year selected in a dropdown menu, showcasing the top countries that contribute to CO₂ emissions.
Prerequisites
Before we begin, ensure you have the following installed:
- Node.js and npm
- Basic understanding of React
Setting Up the React Project
To get started, we’ll set up a basic React app using create-react-app. Run the following commands to scaffold a new project:
npx create-react-app co2-emission-chart
cd co2-emission-chart
After the project is set up, install CanvasJS React Charts, a JavaScript library that simplifies the creation of interactive and responsive charts for data visualization.
npm install @canvasjs/react-charts
Next, we'll install react-loader-spinner to show a loading indicator while the data is being fetched.
npm install react-loader-spinner
Now that everything is installed, you're prepared to start creating the chart
Fetching CO₂ Emission Data from the World Bank API
The World Bank Data API provides access to a wide range of global data, including CO₂ emissions. For this article, we'll be focusing on carbon dioxide (CO2) emissions measured in kilotons for all countries.
The API endpoint we’ll be using looks like this:
https://api.worldbank.org/v2/country/all/indicator/EN.ATM.CO2E.KT?date=2020&format=json
This API endpoint retrieves data on carbon dioxide (CO2) emissions measured in kilotons for all countries for the year 2020. The indicator EN.ATM.CO2E.KT represents the total amount of CO2 emissions produced by a country.
Creating the React Component for fetching CO₂ Emissions & displaying in chart
Let’s now create a component EmissionChart.js
that fetches the data and displays it using CanvasJS. Inside your src
folder, create a new file EmissionChart.js and add the following code:
import { useState, useEffect } from 'react';
import CanvasJSReact from '@canvasjs/react-charts';
let CanvasJS = CanvasJSReact.CanvasJS;
let CanvasJSChart = CanvasJSReact.CanvasJSChart;
function EmissionChart() {
const [emissionDps, setEmissionDps] = useState([]);
const [yearSelected, setYearSelected] = useState(2020);
const years = [];
for (let i = 0; i < 15; i++) {
years.push(2020 - i);
}
let countriesCount = 10;
let options = {
title: {
text: `Top ${countriesCount} CO₂ Emitting Countries`,
},
subtitles: [{
text: `World Bank Data for ${yearSelected}`
}],
animationEnabled: true,
theme: 'light2',
axisY: {
title: 'CO₂ emissions (kt)',
labelFormatter: (e) => addSymbols(e.value),
suffix: 'kt'
},
data: [{
type: 'bar',
yValueFormatString: '#,###kt',
dataPoints: emissionDps,
}],
};
function addSymbols(value) {
var suffixes = ['', 'K', 'M', 'B'];
var order = Math.max(Math.floor(Math.log(value) / Math.log(1000)), 0);
if (order > suffixes.length - 1) order = suffixes.length - 1;
var suffix = suffixes[order];
return CanvasJS.formatNumber(value / Math.pow(1000, order)) + suffix;
}
async function fetchCountries() {
const response = await fetch(
'https://api.worldbank.org/v2/country?format=json&per_page=300'
);
const data = await response.json();
// Filter out non-countries (regions, aggregates) by checking if country code is not 'XD' or similar
const validCountries = data[1].filter(
(country) => country.region.id !== 'NA' && country.incomeLevel.id !== 'XD'
);
// Create a set of country codes for quick lookup
const countryCodes = new Set(validCountries.map((country) => country.id));
return countryCodes;
}
async function fetchEmissionData(baseUrl) {
let emissionRecords = [];
let page = 1;
let morePagesAvailable = true;
// Looping around pages if exist more
while (morePagesAvailable) {
// Construct URL for the current page
const url = `${baseUrl}&page=${page}`;
try {
const response = await fetch(url);
const data = await response.json();
// World Bank API returns metadata in the first element, data in the second
const [metadata, records] = data;
// Append the current page's data to allData
emissionRecords = emissionRecords.concat(records);
// Check if there are more pages based on metadata
const totalPages = metadata.pages;
if (page >= totalPages) {
morePagesAvailable = false;
} else {
page++;
}
} catch (error) {
console.error('Error fetching data:', error);
break;
}
}
// Filtering the record as the world bank API contains data for World, regions, etc.
var countryCodes = await fetchCountries();
emissionRecords = emissionRecords.filter((record) => {
return record.value !== null && countryCodes.has(record.countryiso3code);
});
emissionRecords.sort((a, b) => b.value - a.value);
// Parse the emission record data in CanvasJS datapoint format
let dps = [];
for (let i = 0; i < countriesCount; i++) {
dps.push({
label: emissionRecords[i].country.value,
y: emissionRecords[i].value,
});
}
setEmissionDps(dps);
}
useEffect(() => {
fetchEmissionData(
`https://api.worldbank.org/v2/country/all/indicator/EN.ATM.CO2E.KT?date=${yearSelected}&format=json`
);
}, [yearSelected]);
return (
<>
<div className="year-selection">
<label>
Select Year:
<select
onChangeCapture={(e) => setYearSelected(e.target.value)}
defaultValue={yearSelected}
>
{years.map((year, index) => (
<option value={year}>{year}</option>
))}
</select>
</label>
</div>
<div className="container">
<CanvasJSChart
options={options}
containerProps={{ width: '100%', height: '360px' }}
/>
</div>
</>
);
}
export default EmissionChart;
Creating the Component for displaying loader while fetching data
Let’s build a Loader component that will be shown while data is being fetched. Additionally, we will introduce a state variable isLoading
in the EmissionChart component, which will serve as a flag to determine whether to display the chart or the loader.
/*Loader.js*/
import { Bars } from 'react-loader-spinner';
function Loader({ yearSelected }) {
return (
<>
<Bars
height="80"
width="80"
color="#6f76ab"
ariaLabel="Loading Data from World Bank API"
animationDuration="0.75"
wrapperStyle={{}}
visible={true}
/>
<div style={{ textAlign: 'center', marginTop: '16px' }}>
Hang on for a moment! <br />
We're pulling CO₂ emissions data for {yearSelected} from the World Bank
</div>
</>
);
}
export default Loader;
/*EmissionChart.js*/
import Loader from './Loader';
.
.
const [isLoading, setIsLoading] = useState(true);
async function fetchEmissionData(baseUrl) {
setIsLoading(true);
.
.
setEmissionDps(dps);
setIsLoading(false);
}
.
.
.
return (
<>
<div className="year-selection">
<label>
Select Year:
<select
onChangeCapture={(e) => setYearSelected(e.target.value)}
defaultValue={yearSelected}
>
{years.map((year, index) => (
<option value={year}>{year}</option>
))}
</select>
</label>
</div>
<div className="container">
{isLoading ? (
// Display the loader spinner while fetching data from World Bank API
<Loader yearSelected={yearSelected} />
) : (
// Display the chart when the data is loaded
<>
<CanvasJSChart
options={options}
containerProps={{ width: '100%', height: '360px', maxWidth: '920px', margin: 'auto' }}
/>
</>
)}
</div>
</>
);
.
.
Using the Component in App.js
With the EmissionChart
component complete, it's time to integrate it into the main application. Open src/App.js
and update it as follows:
/*App.js*/
import EmissionChart from './EmissionChart';
import './App.css';
function App() {
return (
<EmissionChart />
);
}
export default App;
Adding styles to our Component
To improve the appearance of our component, you can add some CSS styles. You can include the following lines in src/App.css
#root {
height: 100vh;
width: 100%;
background: #fff;
color: #000;
}
body {
background: #fff;
color: #000;
}
.year-selection {
text-align: center;
margin-bottom: 16px;
margin-top: 16px;
display: flex;
justify-content: center;
width: auto;
}
.year-selection select {
margin-left: 8px;
background: #fff;
color: #000;
border-radius: 4px;
font-size: 16px;
}
.container {
height: 360px;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.credit-data {
display: block;
font-size: 10px;
color: #8a8484;
max-width: 920px;
width: 100%;
text-align: right;
}
.credit-data a {
margin-left: 2px;
margin-right: 2px;
}
Running the Application
All set! You can now run the application by simply using:
npm start
This will start the React app, and when you visit http://localhost:3000, you should see the loading spinner while the data is being fetched, followed by the chart displaying global CO₂ emissions from 2006 to 2020.
Conclusion
In this article, we illustrated how to create a chart displaying the top countries contributing to CO₂ emissions using data from the World Bank API. We’ve established a solid foundation for building a comprehensive dashboard. This dashboard can be utilized to present various environmental statistics, track trends, and support informed decision-making. Happy coding, and let’s keep making a positive impact together!
Top comments (0)