DEV Community

loading...
Cover image for Create a COVID-19 Data Visualization with Chart.js and React.

Create a COVID-19 Data Visualization with Chart.js and React.

justinjunodev profile image Justin Juno ・6 min read

There are a plethora of websites using data visualizations to help us understand the impacts of the Coronavirus in our respective countries and communities. As it continues to spread, I imagine we will see a lot more but this isn't a bad thing.

Visualizations help people consume knowledge that may be hard to describe or digest in other formats. Not to mention, from a developers perspective they are a lot of fun to work with and build.

In this tutorial, we are going to create a horizontal bar chart using Chart.js that will display the following COVID-19 information for every state: total positive test, total negative test, and total test given. To keep our UI tidy, data will only be displayed for one state at a time and users will have a menu to select from and view other states.

Here is a preview of what we will be building:

Let's Get Started.

1. Project Setup

Open your terminal and create a new react project with create-react-app. I've named mine devto-covid-tracker, but you can choose a different name.

#terminal
npx create-react-app devto-covid-tracker
cd devto-covid-tracker
Enter fullscreen mode Exit fullscreen mode

Unfortunately, create-react-app includes some boilerplate that isn't necessary for this tutorial. In the project src directory, remove all of the files except for index.js and App.js. Then update the contents of each file to match mine below. This way we can start from a blank slate.

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode
// src/App.js
import React from 'react';

function App() {
  return (
    <div style={{width:"600px", textAlign:"center"}}>
      <h1>COVID-19 Test Tracker</h1>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

2. Fetching Our Data

Now that we are set up, let's grab our data. For this tutorial, we will use the COVID Tracking Project API. We will use their States Current Values endpoint. This endpoint accepts a query param (state abbreviation) that will return the data for that specific state. We will store this query in our application state as activeQuery using React's useState hook. For now, we will hard-code the value as NY for New York.

Then we will wrap our API request in React's useEffect hook and listen for any updates to this query. When our app initially loads or an update is made to our query, useEffect will run and grab the data from our new endpoint. We'll store this data in a separate useState hook called stateData and will pass it into our chart later.

// src/App.js
import React, {useState, useEffect} from 'react';

function App() {
  const [activeQuery, setActiveQuery] = useState("NY")
  const [stateData, setStateData] = useState({})

  useEffect(() => {
    async function getData() {
      const res = await fetch(
        `https://covidtracking.com/api/states?state=${activeQuery}`
      );
      const data = await res.json();
      setStateData(data);
    }
    getData();
  }, [activeQuery]);

  return (
    <div style={{width:"600px", textAlign:"center"}}>
      <h1>COVID-19 Test Tracker</h1>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

3. Creating The Menu

Our menu will be a form with a select field that will include an option for each state in the United States. Fortunately, there is a dataset on npm that we can install so we won't have to type each state abbreviation by hand. Return to your terminal and install the following package.

#terminal
npm i datasets-us-states-abbr
Enter fullscreen mode Exit fullscreen mode

Let's import our state abbreviations as stateAbbr and a create a menu for our users. This menu will be a form with an onChange event. This event will trigger anytime a change is made to the forms select field. So in this instance, when a user selects a new option, we will take that value (states abbreviation) and update our current activeQuery with it using setActiveQuery.

Since the stateAbbr dataset is imported as an object, we will use Object.values to create an array of the values of our object. Then we will map over the keys and return an option for each state.

// src/App.js
import React, {useState, useEffect} from 'react';
import * as stateAbbr from "datasets-us-states-abbr";

function App() {
  const [activeQuery, setActiveQuery] = useState("NY")
  const [stateData, setStateData] = useState({})

  useEffect(() => {
    async function getData() {
      const res = await fetch(
        `https://covidtracking.com/api/states?state=${activeQuery}`
      );
      const data = await res.json();
      setStateData(data);
    }
    getData();
  }, [activeQuery]);

  console.log(stateData)
  return (
    <div style={{width:"600px", textAlign:"center"}}>
      <h1>COVID-19 Test Tracker</h1>
      <form>
        <label>
          Select a state:
          <select value={activeQuery} onChange={e => setActiveQuery(e.target.value)}>
            {Object.values(stateAbbr).map(abbr => {
              return (
                <option key={abbr} value={abbr}>
                  {abbr}
                </option>
              );
            })}
          </select>
        </label>
      </form>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

4. Props and Data Structure

In your src directory create a new component called Chart.js. Before adding any code to the file, let's go ahead and import it into our App.js file and place the component below our form. Since this component will need access to our stateData, we will pass it as a prop. Now that we've got this in place, our work in App.js is done.

// src/App.js
import React, {useState, useEffect} from 'react';
import * as stateAbbr from "datasets-us-states-abbr";
import Chart from "./Chart.js"

function App() {
  const [activeQuery, setActiveQuery] = useState("NY")
  const [stateData, setStateData] = useState({})

  useEffect(() => {
    async function getData() {
      const res = await fetch(
        `https://covidtracking.com/api/states?state=${activeQuery}`
      );
      const data = await res.json();
      setStateData(data);
    }
    getData();
  }, [activeQuery]);

  return (
    <div style={{width:"600px", textAlign:"center"}}>
      <h1>COVID-19 Test Tracker</h1>
      <form>
        <label>
          Select a state:
          <select value={activeQuery} onChange={e => setActiveQuery(e.target.value)}>
            {Object.values(stateAbbr).map(abbr => {
              return (
                <option key={abbr} value={abbr}>
                  {abbr}
                </option>
              );
            })}
          </select>
        </label>
      </form>
      <Chart data={stateData} />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Before we build our visualization, we need to structure our data so that it'll play nicely with our chart. To do this we will start by creating our Chart.js component. We will pass in our data prop, de-structure it, and create a new dataStucture (object) to pass into our chart.

// src/Chart.js
import React from 'react'

const Chart = ({data}) => {
    const {positive, negative, totalTestResults, dateModified} = data

    const dataStructure = {
        positive,
        negative,
        total: totalTestResults,
    }

    return (
        <div>
            <h2>Our Future Bar Chart!</h2>
        </div>
    )
}

export default Chart
Enter fullscreen mode Exit fullscreen mode

5. Creating The Visualization

Return to your terminal and install the chart.js and react-chartjs-2 packages. The second package provides a React wrapper for chart.js. Making it a lot easier to work with and a great candidate for a tutorial and project like this.

#terminal
npm i chart.js react-chartjs-2
Enter fullscreen mode Exit fullscreen mode

Let's go back to our Chart.js and import the HorizontalBar from react-chartjs-2. Just as the name would imply, this is our horizontal bar chart. Replace the current h2 tag with it.

// src/Chart.js
import React from 'react'
import { HorizontalBar } from "react-chartjs-2";

const Chart = ({data}) => {
    const {positive, negative, totalTestResults} = data

    const dataStructure = {
        positive,
        negative,
        total: totalTestResults,
    }

    return (
        <div>
            <HorizontalBar />
        </div>
    )
}

export default Chart
Enter fullscreen mode Exit fullscreen mode

All we have to do now is create a config object for our HorizontalBar. We will use this config to pass all of our data and options for this chart. For tutorial purposes, I'm going to keep the options minimal.

Create a new object called chartDataConfig. Since our chart will need labels, we'll start by creating a labels arrays with the keys from our dataStructure object. Next, we will create a dataSets array that will house an object with our data and options. Since we want our data to match our labels, we will create an array with the values from our dataStructure object.

Next, we will add a label for our key. This will let our users know what the bars represent on our chart. Then we will pass some additional color options to customize the look and feel of our chart. You can experiment here and make this chart your own. Lastly, we'll pass the chartDataConfig to our charts data prop.

// src/Chart.js
import React from 'react'
import { HorizontalBar } from "react-chartjs-2";

const Chart = ({data}) => {
    const {positive, negative, totalTestResults} = data

    const dataStructure = {
        positive,
        negative,
        total: totalTestResults,
    }

    const chartDataConfig = {
        labels: Object.keys(dataStructure),
        datasets: [
            {
                data: Object.values(dataStructure),
                label: "COVID-19 Test Results",
                backgroundColor: "rgba(255,99,132,0.2)",
                borderColor: "rgba(255,99,132,1)",
                borderWidth: 1,
                hoverBackgroundColor: "rgba(255,99,132,0.4)",
                hoverBorderColor: "rgba(255,99,132,1)",
            }
        ]
    };

    return (
        <div>
            <HorizontalBar data={chartDataConfig}/>
        </div>
    )
}

export default Chart
Enter fullscreen mode Exit fullscreen mode

That's it. Return to your terminal and start your React app if you haven't already.

#terminal
npm start
Enter fullscreen mode Exit fullscreen mode

If you followed the steps correctly, you should be able to navigate to your localhost and see your COVID-19 Test Tracker in action. If you are seeing errors, return to your terminal and end the current session ctrl-c and re-run the npm start command again. If errors persist, feel free to reference this project on Code Sandbox or GitHub.


Thanks for reading!

I sincerely appreciate you taking the time to read this article. If you found it helpful, please give it some love or share it with your friends. If there are additional topics you'd like me to cover in the future, let me know in the comments.

Peace. ✌️♥️💻


Cover Photo by CDC on Unsplash

Discussion (0)

pic
Editor guide