Create Interactive Charts With Recharts
Using React and Recharts to create an interactive dashboard
In this article, we will focus on a library named Recharts to create interactive 2d charts. For this, we will use the Covid-19 api to display not only Covid19 data to compare countries but also show historical data of each country. We will first create a table showing all the countries and use a click function to show the historical data of a country.
Setting up our developer environment
For this tutorial, we are going to use React. Instead of setting up your own React project, I have built a basic project so you can start off right away with coding instead of needing to configure your project. clone this repository and follow the steps below.
git clone git@github.com:Ugur22/recharts-basics.gitcd recharts-basicsnpm installnpm start
For this project we are going to use the following tools to create a Covid-19 dashboard:
- Recharts — charts library to draw graphs.
- Moment.js — Parse and display dates.
- Bulma — CSS framework for styling and grid.
- Sass CSS — easy reuse of CSS and mixins.
After you’re done you should see the following chart on your web-app:
Great now that is all set and done we can start building the dashboard. In your App.jsx
you can see the following code that displays your chart. As you can see Recharts requires very little code to build a complex chart. First, we import the needed components we need for our chart. Because we used a Line Chart in this example we also needed to import Line Chart and Line. If you wanted to use for example an Area Chart you could replace them with AreaChart
and Area. The YAxis
is used to display the values onto the graph and the XAxes
to spread them across horizontally. Later we will use the XAxes
to display the dates so you can see what value occurs at which date. The Tooltip component gives you an entire tooltip without any extra code when you hover over every data point. On the Line element, you can also see a property named dataKey
. With this, you can choose which field from your data you want to display on your chart. In this case, you can see that for the first line it shows the pv
value for every Page and for the second line it uses the uv
field.
import { LineChart, Line, XAxis, YAxis, Tooltip, Legend} from "recharts";const data = [
{ name: 'Page A', uv: 4000, pv: 2400, amt: 2400 },
{ name: 'Page B', uv: 3000, pv: 1398, amt: 2210 },
{ name: 'Page C', uv: 2000, pv: 9800, amt: 2290 },
{ name: 'Page D', uv: 2780, pv: 3908, amt: 2000 },
{ name: 'Page E', uv: 1890, pv: 4800, amt: 2181 },
{ name: 'Page F', uv: 2390, pv: 3800, amt: 2500 },
{ name: 'Page G', uv: 3490, pv: 4300, amt: 2100 },
];function App() {
return (
<div className="App">
<LineChart width={800} height={400} data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" />
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
</div>
);
}
Let’s try to change this chart so you can get an idea of how Recharts works. Try to replace Line with Area and LineChart
with AreaChart
. If you take a look at your chart now u should see the same data displayed with an area chart instead.
You can also play around with the data a bit by changing the values to see how it affects the chart. Below the chart, you can also see the legend that is displayed for each graph we draw representing the names of the dataset.
Now that we have an idea of how to draw a chart in Recharts let’s use this to display a chart of real API data instead of mock-up data. As stated above we will use the novelcovid19 API for this to display Covid-19 data of a single country.
To get the data from an API we need to store it first in a state. For this, we will use useState
and useEffect
from React like below
import React, { useState, useEffect } from 'react';
import { AreaChart, Area, XAxis, YAxis, Tooltip, Legend} from "recharts";function App() {
let [data, setData] = useState([]); useEffect(() => {
fetchData();
}, []) const fetchData = () => {
fetch(`https://api.covid19api.com/total/country/Italy`)
.then(response => response.json())
.then(json => setData(json))
}// Added to filter out zero values form the API
data = data.filter(a => (a.Active !== 0 && a.Recovered !== 0 & a.Deaths !== 0 ));console.log(data);return (
<div className="App">
<AreaChart width={800} height={400} data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Area type="monotone" dataKey="pv" stroke="#8884d8" />
</AreaChart>
</div>
);
}
With useEffect
we can call the FetchData()
function which in turn will do an API call through the fetch method. In my case I choose but u can choose whatever country you prefer. By using SetData
we can store the API data in the variable data. To be sure the API call works correctly we will console.log
the data. If done correctly you should get a similar output as below.
Now you are probably wondering why your chart does not show anything even though you have pointed to data in AreaChart
. This is because Recharts also needs to know what values need to be displayed on the XAxis
and the datakey
for the Area let’s do that right now.
For the XAxes
we can add Date as adatakey
and in the Area
, we will add a value to display the Covid-19 cases. In the output above you can see which values we can choose from. You can choose whichever you like. For example, if I choose Active I get all the active cases per day on my chart like below.
<Area type="monotone" dataKey="Active" stroke="#8884d8"
If done correctly you should see a chart appearing like the one above showing the Covid-19 cases. One thing that we do notice is that the date is not yet formatted correctly in the X-axes. This can be fixed by using moment.js so let’s do that quickly. so let’s import moment.js and then use moment to format the date to the desired format.
import moment from 'moment';
For this, we will create a function called CustomizedAxisTick. You can take a look at the site of moment.js to find the format you prefer. I choose the ll format because I like the shorthand notation of the month with the day. After formatting, I use slice to cut off the year since we don’t need that in this example.
const CustomizedAxisTick = ({ x, y, payload }) => {
const dateTip = moment(payload.value)
.format("ll")
.slice(0, 6);
return (
<g transform={`translate(${x},${y})`}>
<text x={23} y={0} dy={14} fontSize="0.90em" fontFamily="bold" textAnchor="end" fill="#363636">
{dateTip}</text>
</g>
);
}
After creating this function you can add another property to the XAxes
called tick and add our new function to it as follows:
<XAxis dataKey="Date" tick={CustomizedAxisTick} />
After adding this your chart should display the dates correctly like below. I have also changed the color to orange because it suits active cases more than the blue color.
<Area type="monotone" dataKey="Active" fill="#e67e22"
Great now we have a working chart showing real data from an API. You can play around with this a little bit by changing the datakey
for Area to see how it affects the chart. So now that we have your first working chart let’s add some interactivity to it.
So let’s first add a function to customize the styling and formatting of the tooltip.
const CustomTooltip = ({ active, payload, label }) => {
const dateTip = moment(label)
.format("llll")
.slice(0, 12);
const formattedDate = dateTip
if (payload === null) return
if (active)
return (
<div className="custom-tooltip">
<p className="label-tooltip">{`${formattedDate}`}</p>
<p className="desc-tooltip">
<span className="value-tooltip">Total Cases: {payload[0].value.toLocaleString()}</span>
</p>
</div>
);
return null;
};
Next to this, you will also need to add this styling to the style.scss
to give the tooltip a clean look.
.custom-tooltip {
padding: 10px;
background-color: rgba(255, 255, 255, 0.7);
border: 2px solid #c3c3c3;
border-radius: 10px; span {
font-weight: bold;
}
}
Now we can add the CustomTooltip
function to the tooltip as follows. You can also add an animationDuration
property to change the delay the tooltip has when you hover over to another value. I have set mine to zero for it to have no delay.
<Tooltip content={<CustomTooltip />} animationDuration={0} />
Now for some real interactivity, we are also going to add a brush component. This component allows the user to select only a certain range of the data with the help of a slider. To add this we first need to add another custom function to format the date correctly. Even though we are formatting the same date we used for the Tooltip we have to create another one because the Brush component doesn’t accept the HTML elements which are returned in the CustomizedAxisTick
function.
const xAxisTickFormatter = (timestamp_measured) => {
return moment(timestamp_measured)
.format("ll")
.slice(0, 6);
}
Now let’s add the brush component to our chart. You can put it in the AreaChart
.
<AreaChart width={800} height={400} data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
<XAxis dataKey="Date" tick={CustomizedAxisTick} />
<YAxis />
<Tooltip content={<CustomTooltip />} animationDuration={0}/>
<Legend />
<Area type="monotone" dataKey="Active" fill="#e67e22"
stroke="#e67e22" />
<Brush tickFormatter={xAxisTickFormatter} dataKey="Date" />
</AreaChart>
After adding the Tooltip and the brush correctly your chart should work like below.
Your chart is now much more interesting because the brush allows the user to zoom in on a specific range of dates to make new observations. Next to this the updated tooltip now shows you the number of cases per day making it more obvious for the user to track the highlighted data. So now that we have a fully working chart with some interactivity let’s try to create a dashboard. We first want to create three columns above the charts showing the Covid-19 numbers for each type of case (active, recovered, and death).
Let’s first get the latest value of each case type. we can use the spread operator for this with Math.max
for each value like below. next to that we can also get the country name with data.map and slice it to 1 so we only get a single value.
const amount_Active = data.map((a) => a.Active);
let latest_Active = Math.max(...amount_Active);const amount_deaths = data.map((a) => a.Deaths);
let latest_deaths = Math.max(...amount_deaths);const amount_recovered = data.map((a) => a.Recovered);
let latest_recovered = Math.max(...amount_recovered);const getCountries = data.map((a) => a.Country);
country = getCountries.slice(0, 1);
If you console.log()
this you should get the latest values for each case type and the country name from the Covid-19 API. Next, we also need to add useState
variables so we can let react know which button is pressed and what styling it should get accordingly.
const orange = '#e67e22';const red = '#e74c3c';const green = '#27ae60';let [color, setColor] = useState(orange);let [activeIndex, setActive] = useState(0);let country;
Now we can set up our BUTTONS
array.
const BUTTONS = [
{
name: "Active",
color: orange,
value: latest_Active,
id: 1
},
{
name: "Deaths",
color: red,
value: latest_deaths,
id: 2
},
{
name: "Recovered",
color: green,
value: latest_recovered,
id: 3
},
]
After adding this we can use this array to loop over this array in our HTML.
<div className="dashboard">
<h1 className="title is-3">{country} Covid-19 cases</h1>
<div className="columns dashboard__numbers">
{BUTTONS.map((item, index) =>
<div className="column" key={index} >
<h2>
<button style={{ color: item.color === color ? color : "#000" }} onClick={() => [setType(item.name), setActive(index),
setColor(item.color)]} className={activeIndex === index ? 'column__button title is-3 selected' : 'column__button title is-3'}>
{item.name}
</button>
</h2>
<p className="subtitle is-4" >{item.value.toLocaleString()}</p>
</div>
)}
</div>
<div className="columns">
<AreaChart width={800} height={400} data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
<XAxis dataKey="Date" tick={CustomizedAxisTick} />
<YAxis />
<Tooltip content={<CustomTooltip />} animationDuration={0} />
<Legend />
<Area type="monotone" dataKey={type} fill={color} stroke={color} />
<Brush tickFormatter={xAxisTickFormatter} startIndex={Math.round(data.length * 0.45)} />
</AreaChart>
</div>
</div>
also change the className
“app” to ”dashboard” and add the dashboard.scss
as an import to style.scss
and remove the styling for the .App class. If you now take a look at the dashboard.scss
you can see I have already added the styling for the columns and charts. I`ve already added the styling so we canfocus on Recharts for this tutorial instead of css.
@import 'dashboard';
Your dashboard should now look like the one below showing the latest figures for each case type.
As you can see whenever we click on the buttons it gets highlighted with a color and a box-shadow.
<button style={{ color: item.color === color ? color : "#000" }} onClick={() => [setType(item.name), setActive(index),
What we want to do next is to change the chart data by selecting a specific case type by pressing a button. You can see that we already added a setType
to the onClick
on the button which stores the value into the type variable. So all we need to do now is add this value to the AreaChart
.
We can easily now add the type variable to the datakey
property instead of a string. next to this, we can also add color to the fill and stroke value to also make the color of the chart dynamic.
<Area type="monotone" dataKey={type} fill={color} stroke={color} />
You also now have a cool animation whenever you change the case type.
For the sake of keeping this tutorial simple, we will end it here and instead give you some homework to improve this dashboard. First of all, you can try to add multiple charts next to the existing one to create a real dashboard. Try to experiment with different chart types such as bar-charts, line-charts, and circle charts. You can add these charts in the same way we added the AreaChart
. Apart from this, you can also add a drop-down menu that allows the user to switch countries. For this, you will need to add a parameter to the API call to make it dynamic. It would look something like this.
https://api.covid19api.com/total/country/${country}`
If you want some inspiration on how to improve your dashboard you can take a look at mine that I build for this tutorial as an example.
Resources used in this article…
- Recharts - Recharts website
- Covid-19 API - Covid-19 API
- Recharts example dashboard - Covid-19 dashboard