The idea is simple first we are going to fetch the data of all the country which are infected from here novelcovid API. When the user clicks on the country flag it should display all the information such as cases, deaths, total number of cases, etc.
We will then display a graph which will contain two information:
- Total number of cases and
- Total number of deaths in that country.
Implementation
For our app, we will require two dependencies: Material UI for styling and another is React-vis which is a react framework created by uber for drawing graph and chart.
Install both the packages by writing the following commands:
npm install i @material-ui/core react-vis
Now let’s create our first component named App.js
which will fetch the data. Open up your editor and write the following code:
App
import React from 'react';
import AllCountry from "./AllCountry";
import CssBaseline from '@material-ui/core/CssBaseline';
import Container from '@material-ui/core/Container';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import CircularProgress from '@material-ui/core/CircularProgress';
const URL = "https://corona.lmao.ninja/countries"
const useStyle = makeStyles((theme) => ({
paper: { display : 'flex',
flexWrap: 'wrap',
'& > *': {
margin: theme.spacing(3),
width: theme.spacing(700),
height:theme.spacing(70),
},
},
loading: {
'& > *': {
margin: theme.spacing(20),
marginLeft: '45%',
},
}
}));
const App = () => {
const [data,setData] = React.useState(null);
const classes = useStyle();
React.useEffect( () => {
setTimeout(() => {
fetch(URL).then(response => {
if( response.ok ) { return response.json(); }
else { throw new Error("Something Went Worng"); }
})
.then( data => setData(data))
.catch(error => {console.log(error);})
},5000);
});
return (
<div >
<CssBaseline />
<Container maxWidth='lg' >
<div className = {classes.paper}>
<Paper evaluation = {3} >
{
(data !== null) ?
<AllCountry data={data} /> :
<div className = {classes.loading} >
<CircularProgress size = {100}/>
</div>
}
</Paper>
</div>
</Container>
</div>
)
}
export default App;
In the above code, we have used here React.useEffect
which is the new feature of react called React hook which is called whenever our component gets mounted. In this method, we fetch our data from the site.
Then in the App
function we have first defined our state using React.useState
method initially which is null
. The state which in our case is the data
gets updated every 5 seconds.
Then in return
part, we simply check whether the data
is null or not that is whether the data is fetched from the website or not. If not it will show us a circular progress bar or if the data is fetched this data is passed to AllCountry
component as props.
AllCountry
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';
import GridListTileBar from '@material-ui/core/GridListTileBar';
import Typography from '@material-ui/core/Typography'
import Display from './Display';
const useStyle = makeStyles((theme) => ({
gridlayout: {
display : 'flex',
flexWrap: 'wrap',
margin: theme.spacing(1),
justifyContent: 'space-around',
overflow: 'hidden',
},
gridList: {
width : 700,
height : 450,
},
heading: {
margin: theme.spacing(1),
},
}));
function handleFlagClick(index,data,setData) {
const url = "https://corona.lmao.ninja/v2/historical/" + data[index].country
fetch(url).then(response => {
if( response.ok ) { return response.json() }
else { throw new Error("Something Went Worng"); }
})
.then( d => setData({
"overall": data,
"historic": d,
"index" : index}))
.catch(error => {console.log(error);})
}
const AllCountry = (props) => {
const classes = useStyle();
const [countryData,setData] = React.useState(null);
return(
<div className>
{
(data === null) ?
<div className = {classes.gridlayout}>
<Typography className = {classes.heading}
variant = "h4"
color = "primary">
All Country
</Typography>
<GridList className = {classes.gridList} cols = {4} spacing = {5}>
{
props.data.map((d,index) => (
<GridListTile key = {d.country.flag} >
<img className = {classes.button}
id = {index}
onClick = {(e)=>{handleFlagClick(e.target.id,props.data,setData);}}
src = {d.countryInfo.flag} />
<GridListTileBar
title={d.country}
subtitle={<span>{d.countryInfo.iso3}</span>}
/>
</GridListTile>
))
}
</GridList>
</div> :
<div>
<Display index = {countryData.index} overall = {countryData.overall} history = {countryData.historic} />
</div>
}
</div>
);
}
export default AllCountry;
In this component we display all the country flags along with the country name in a Grid from. Whenever a user clicks on the certain flag it triggers handleFlagClick
function. This function takes the index of the flag which was clicked and the name of that country. After taking name it fetches the historic data of that country and updates the state which in our case is countryData
.
After getting the country name and its historic data, this data is passed through Display
component where it gets displayed.

Display
import React from 'react';
import '../../node_modules/react-vis/dist/style.css';
import DiscreteColorLegend from '../../node_modules/react-vis/dist/legends/discrete-color-legend';
import {XYPlot,LineSeries} from 'react-vis';
import {HorizontalGridLines,VerticalGridLines} from 'react-vis';
import {XAxis,YAxis} from 'react-vis';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box'
import Divider from '@material-ui/core/Divider';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import AllCountry from './AllCountry';
function getPlottingData(history)
{
const data = [];
var i = 0;
for(var date in history )
{
data[i] = { x : Date.parse(date), y : history[date] }
i++;
}
return data
}
const useStyle = makeStyles((theme) => ({
content: {
margin: theme.spacing(7),
},
graph: {
marginLeft: theme.spacing(15),
marginTop: theme.spacing(3),
}
}));
const Display = (props) => {
const classes = useStyle();
const [buttonClicked,setState] = React.useState(false)
var items = [
{title: 'Deaths', color: 'red'},
{title: 'Cases', color: 'blue'},
]
return(
<div >
{
(buttonClicked === false) ?
<Box display = "flex" flexDirection = "row">
<Box className = {classes.content} display = "flex" flexDirection = "column" >
<Typography color = 'primary' variant = 'h3'>
{props.overall[props.index].country}
</Typography>
<br />
<Typography color = "textSecondary" variant = "body1" >
Total Cases: {props.overall[props.index].cases}
</Typography>
<Divider variant = "middel" />
<Typography color = "primary" variant = "body1" >
Today Cases: {props.overall[props.index].todayCases}
</Typography>
<Divider variant = "middel" />
<Typography color = "secondary" variant = "body1" >
Total Death: {props.overall[props.index].deaths}
</Typography>
<Divider variant = "middel" />
<Typography color = "secondary" variant = "body1" >
Today Death: {props.overall[props.index].todayDeaths}
</Typography>
<Divider variant = "middel" />
<Typography color = "success" variant = "body1" >
Recovered: {props.overall[props.index].recovered}
</Typography>
<Divider variant = "middel" />
<Typography color = "textSPrimary" variant = "body1" >
Active: {props.overall[props.index].active}
</Typography>
<Divider variant = "middel" />
<Typography color = "error" variant = "body1" > Critical: {props.overall[props.index].critical}
</Typography>
<Divider variant = "middel" />
<br />
<br />
<Button onClick = {() => { setState(true) } } color = 'primary' variant = 'contained' >
Back
</Button>
</Box>
<Box display = "flex" className = {classes.graph} >
<XYPlot xType="time" height = {500} width = {600} >
<XAxis tickLabelAngle={-45} />
<YAxis tickLabelAngle={-90} />
<VerticalGridLines />
<HorizontalGridLines />
<LineSeries
data={getPlottingData(props.history.timeline.deaths)}
strokeWidth = {5}
color = 'red'
/>
<LineSeries
data={getPlottingData(props.history.timeline.cases)}
strokeWidth = {5}
/>
</XYPlot>
<DiscreteColorLegend
height={100}
width={100}
items={items}
/>
</Box>
</Box> :
<AllCountry data = {props.overall} />
}
</div>
)
}
export default Display;
The Display
component displays the corona data. It uses the material’s Box
component to make for layout which makes the graph on the right side and remaining information on the left side of the screen. For the graph, we have used react-vis framework. The way it draws graph is first it takes height and widht of the graph using XYPlot
component. We then make the grid in our graph by using HorizontalGridLines
and VerticalGridLines
which draws horizontal and vertical lines respectively. We have used here LineSeries
component which draws lines in the graph. The data is passed as props which consist of x-axis points and y-axis points. The DiscreteColorLegend
component displays the legend.
