<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ coronavirus - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ coronavirus - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 09 May 2026 19:40:41 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/coronavirus/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to add Coronavirus (COVID-19) case statistics to your React map dashboard with Gatsby ]]>
                </title>
                <description>
                    <![CDATA[ Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world? Author's note: Similar to be... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-coronavirus-covid-19-case-statistics-to-your-map-dashboard-in-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66bee8e6bc07dbcebef938dc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 22 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-mapping-app-2600x1000.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world?</p>
<p><em>Author's note: Similar to before, this dashboard is meant to be a demo and proof of concept for using real world data to build a dashboard. While this data should be accurate per the NovelCOVID API, I would recommend using tools like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a> for complete and accurate analysis. Stay home and be safe! ❤️</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</a></li>
<li><a class="post-section-overview" href="#heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</a></li>
<li><a class="post-section-overview" href="#heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</a></li>
<li><a class="post-section-overview" href="#heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</a></li>
<li><a class="post-section-overview" href="#heading-what-can-i-do-next">What can I do next?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9bfxeod27fU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We're going to be extending our <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">original map demo</a> with some basic statistics that we can retrieve from the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. To get an idea, here's <a target="_blank" href="https://coronavirus-map-dashboard.netlify.app/">my demo</a> I'm basing this off of.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-covid-19-dashboard-map-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map demo with dashboard statistics</em></p>
<p>While you're not required to have completed <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">Part 1</a> to apply these concepts, it definitely helps, and it lets you set up a map for your dashboard. If you'd like to start there, which I recommend, check out <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App with Gatsby and Leaflet</a> first.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven't played with maps before, don't be discouraged! It's not as bad as you probably think. If you'd rather start with mapping basics, you can  <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a>  first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>For this walkthrough, you pretty much need a React app in some form. I'll be working with the dashboard we previously built in my last walkthrough that includes a <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">map of the cases of the Coronavirus (COVID-19) per country</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-tutorial-country-markers.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map dashboard</em></p>
<p>I recommend starting with the previous tutorial, but if you want to skip the map and start fresh, the easiest way would probably be to use <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a>, <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a>, or <a target="_blank" href="https://nextjs.org/">Next.js</a>.</p>
<h2 id="heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</h2>
<p>To get started with our statistics dashboard, we're going to do a little prep work by changing how we're fetching the data. The goal here, is we're going to wrap our request logic in a reusable way so that we can use it for both our countries data and our new statistics data.</p>
<h3 id="heading-creating-a-new-react-hook-to-fetch-data">Creating a new React hook to fetch data</h3>
<p>Diving in, the first we'll do is create a new <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html">React hook</a> that will serve as how we fetch the data. To get started, create a new file in your hooks directory called <code>useTracker.js</code>  and add a line inside of <code>hooks/index.js</code> to export it:</p>
<pre><code class="lang-js"><span class="hljs-comment">// New file src/hooks/useTracker.js</span>
<span class="hljs-comment">// This will be empty for now</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Inside hooks/index.js</span>
<span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> <span class="hljs-keyword">as</span> useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useTracker'</span>;
</code></pre>
<p>Inside of our <code>useTracker.js</code> file, we're going to set up our request logic. This is a long file, so make sure you copy and paste the entire thing before we walk through what it does:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> API_HOST = <span class="hljs-string">'https://corona.lmao.ninja/v2'</span>;

<span class="hljs-keyword">const</span> ENDPOINTS = [
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'all'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/all'</span>,
    <span class="hljs-attr">isDefault</span>: <span class="hljs-literal">true</span>
  },
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'countries'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/countries'</span>
  }
]

<span class="hljs-keyword">const</span> defaultState = {
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>
}

<span class="hljs-keyword">const</span> useTracker = <span class="hljs-function">(<span class="hljs-params">{ api = <span class="hljs-string">'all'</span> }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> [tracker = {}, updateTracker] = useState(defaultState)

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchTracker</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ id } = {}</span>) =&gt;</span> id === api);

    <span class="hljs-keyword">if</span> ( !route ) {
      route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ isDefault } = {}</span>) =&gt;</span> !!isDefault);
    }

    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'loading'</span>
        }
      });
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${API_HOST}</span><span class="hljs-subst">${route.path}</span>`</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'error'</span>,
          <span class="hljs-attr">error</span>: e
        }
      });
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data } = response;

    updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> {
        ...prev,
        <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>,
        data
      }
    });

  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchTracker()
  }, [api])

  <span class="hljs-keyword">return</span> {
    fetchTracker,
    ...tracker
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useTracker;
</code></pre>
<p>Starting from the top:</p>
<ul>
<li>We import our dependencies: we're going to use Reacts <code>useEffect</code>  and <code>useState</code> hooks to manage our requests</li>
<li>We define default constants: we have a base API endpoint for our data, a list of the available endpoints we'll use, and a state object that will store our data</li>
<li>We define our <code>useTracker</code> hook:  our hook includes one argument <code>api</code>  that will allow us to specify which endpoint we'll use to make our request</li>
<li>We set up a state instance: we'll want to keep track of our fetched data, so we create a <code>tracker</code> state instance that we'll be able to update</li>
<li>We created an asynchronous <code>fetchTracker</code> function: we'll use this to make our actual request</li>
<li>Inside our function: we first find the API route and create our URL, update our state instance to a "loading" state, try to make our request, catch any errors if there are any, and finally if the request is successful, we update our state with that data</li>
<li>We trigger our function: using a <code>useEffect</code> hook, we trigger our <code>fetchTracker</code> function to make the request. We only have one dependency of <code>api</code>. This means the function will only fire the first time and any time the <code>api</code> value we pass in changes. We won't be changing that value, but it may be helpful in other instances if you're dynamically changing the API used</li>
<li>We return our tracker: the returned object includes both our <code>tracker</code> data as well as our <code>fetchTracker</code> function that we could use to refetch the data if we'd like</li>
</ul>
<p>And with all of that, we have a brand new hook that will fetch data from the NovelCOVID API.</p>
<h3 id="heading-using-our-new-tracker-hook">Using our new tracker hook</h3>
<p>To make use of this hook, let's jump over to <code>src/pages/index.js</code>, remove our <code>axios</code> import if it's there, and instead import our hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'hooks'</span>;
</code></pre>
<p>With our hook, let's replace our original country data request.  First, add the following to the top of the <code>IndexPage</code> component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: countries = [] } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'countries'</span>
});

<span class="hljs-keyword">const</span> hasCountries = <span class="hljs-built_in">Array</span>.isArray(countries) &amp;&amp; countries.length &gt; <span class="hljs-number">0</span>;
</code></pre>
<p>This will let us fetch our country data and let us know if we have any results. Next, let's replace our original request.</p>
<p>Inside of our <code>mapEffect</code> function, let's remove the <code>axios</code> request in addition to the response, the destructured data object, and the <code>hasData</code> constant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/code-diff-map-effect-countries-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Code diff showing update to map effect</em></p>
<p>Then, replace <code>hasData</code> with <code>hasCountries</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> ( !hasCountries ) <span class="hljs-keyword">return</span>;
</code></pre>
<p>And replace <code>data</code> with <code>countries</code> in the <code>geoJson</code> object where we map our features:</p>
<pre><code class="lang-js">features: countries.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
</code></pre>
<p>At this point, if you hit save and refresh, you shouldn't notice any difference to what you previously had.</p>
<h3 id="heading-add-a-request-for-our-stats">Add a request for our stats</h3>
<p>Now that we are using our <code>useTracker</code> hook to fetch our country data, let's also use that to fetch our stats.</p>
<p>Right next to where we set up our <code>useTracker</code> hook before, let's add another request:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: stats = {} } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'all'</span>
});
</code></pre>
<p>And if we add a <code>console.log</code> statement under to see what's inside <code>stats</code>:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'stats'</span>, stats);
</code></pre>
<p>We should see our <code>stats</code> data object logged out!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/console-log-coronavirus-stats-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Using console.log to show Coronavirus (COVID-19) statistics</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/fe9d85e57f7474a86d38213676bf62df4b6168a4">Follow along with the commit!</a></p>
<h2 id="heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</h2>
<p>Now that we have our data available to use, let's use it!</p>
<p>To get started adding our statistics to the dashboard, let's create a data structure that will allow us to easily configure the data we want to use.</p>
<p>To do this, let's first create a new array called <code>dashboardStats</code> below <code>hasCountries</code> at the top of the page component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [];
</code></pre>
<p>Inside this array, let's add some new objects that specify our data that we're pulling from the <code>stats</code> object we requested. To start, let's try to add:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Cases'</span>,
      <span class="hljs-attr">value</span>: stats?.cases
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.casesPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Deaths'</span>,
      <span class="hljs-attr">value</span>: stats?.deaths
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.deathsPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Tests'</span>,
      <span class="hljs-attr">value</span>: stats?.tests
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.testsPerOneMillion
    }
  }
]
</code></pre>
<p>The reason we're splitting this up into <code>primary</code> and <code>secondary</code> keys, is we're going to use that to differentiate between logically similar stats that we want to style a little bit differently.</p>
<p>_Note: if you're not familiar with the <code>?.</code> syntax, it's called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining">Optional Chaining</a>. This allows us to chain our properties without worrying about if the objects exist. If <code>stats</code> is undefined, it will simply return undefined instead of throwing an error._</p>
<p>With our stats data, let's add the tracker to our map. Let's remove our current <code>&lt;Map&gt;</code> component and include it nested inside our tracker div in the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Map</span> {<span class="hljs-attr">...mapSettings</span>} /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stats"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      { dashboardStats.map(({ primary = {}, secondary = {} }, i) =&gt; {
        return (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">Stat-</span>${<span class="hljs-attr">i</span>}`} <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat"</span>&gt;</span>
            { primary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-primary"</span>&gt;</span>
                { primary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ primary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            )}
            { secondary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-secondary"</span>&gt;</span>
                { secondary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ secondary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            )}
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        );
      })}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This code should be immediately following the <code>&lt;Helmet&gt;</code> component if you're following along.</p>
<p>To explain what we're doing:</p>
<ul>
<li>We're creating a "tracker" div that will organize our stats</li>
<li>We move our <code>&lt;Map</code> component inside of this tracker</li>
<li>We create a separate section called "tracker-stats"</li>
<li>Inside of this, we create an unordered list (<code>ul</code>)</li>
<li>Inside of our list, we loop through all of our stats inside <code>dashboardStats</code></li>
<li>For each stat, we create a new list element (<code>li</code>) and include 2 optional paragraphs that includes our primary stat data and our secondary stat data</li>
</ul>
<p>Once we reload our page, we should now see a few stats:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-stats-to-page.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding the first statistics to the page</em></p>
<p>Now that we have our stats on our page, let's make them look like they're in a dashboard.</p>
<p>Let's create a new file called <code>_tracker.scss</code> inside of our <code>src/assets/stylesheets/components</code> directory. Once that file is created, additionally add it to the <code>src/assets/stylesheets/components/__components.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@import</span> <span class="hljs-string">"tracker"</span>;
</code></pre>
<p>With our new component style file ready to go, let's add some styles into <code>_tracker.scss</code>:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-stats</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-top</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: grid;
    grid-template-<span class="hljs-attribute">columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat</span> {

  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">border-right</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);
  <span class="hljs-attribute">border-bottom</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-primary</span> {

  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-secondary</span> {

  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">margin</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">margin-left</span>: .<span class="hljs-number">4em</span>;
  }

}
</code></pre>
<p>Above – we're adding colors and organizational effects, such as using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout">CSS Grid</a>, to allow our data to be organized in an easy to read way and to look good! We're also making use of some pre-existing colors variables that are used within the project to keep the color use consistent.</p>
<p>Once you save those styles and reload the page, it should look much better:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-case-statistics-to-map-dashboard.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding case statistics to the dashboard</em></p>
<p>From here, feel free to add more stats or adjust them to your liking. In the demo I created, I added the stats for active cases, critical cases, and recovered cases. If you'd like to do the same, you can <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">check out the commit</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">Follow along with the commit!</a></p>
<h2 id="heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</h2>
<p>Now the rest of this walkthrough could be considered optional, but ultimately we want people to be able to read these statistics, right? So let's make the numbers a little more easy to read.</p>
<p>First, let's open our <code>src/lib/util.js</code> file and add this function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * commafy
 * <span class="hljs-doctag">@description </span>Applies appropriate commas to large numbers
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commafy</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">let</span> numberString = <span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span>;

  numberString = numberString.split(<span class="hljs-string">''</span>);

  numberString.reverse();

  numberString = numberString.reduce(<span class="hljs-function">(<span class="hljs-params">prev, current, index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> shouldComma = (index + <span class="hljs-number">1</span>) % <span class="hljs-number">3</span> === <span class="hljs-number">0</span> &amp;&amp; index + <span class="hljs-number">1</span> &lt; numberString.length;
    <span class="hljs-keyword">let</span> updatedValue = <span class="hljs-string">`<span class="hljs-subst">${prev}</span><span class="hljs-subst">${current}</span>`</span>;
    <span class="hljs-keyword">if</span> ( shouldComma ) {
      updatedValue = <span class="hljs-string">`<span class="hljs-subst">${updatedValue}</span>,`</span>;
    }
    <span class="hljs-keyword">return</span> updatedValue;
  }, <span class="hljs-string">''</span>);

  numberString = numberString.split(<span class="hljs-string">''</span>);
  numberString.reverse()
  numberString = numberString.join(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> numberString;
}
</code></pre>
<p>This function will take a number and turn it into a string with commas. To walk through what it does:</p>
<ul>
<li>Takes in a value as an argument. For our use, this value will most likely be a number.</li>
<li>It converts the value into a string. We'll use this to work with adding commas to our number.</li>
<li>We split that string into an array and reverse it. We want to reverse it because it makes it easier to add our commas depending on the index.</li>
<li>We use the javascript <code>reduce</code> function to recreate our number-string. After every 3 numbers, we want to add a comma.</li>
<li>Once we have our new value with the commas, we want to re-reverse it. So we split it again, reverse the array of characters, and re-join it, which is what we return</li>
</ul>
<p>And now that we have our <code>commafy</code> function, let's use it. Back inside <code>src/pages/index.js</code>, let's import our function at the top of the page:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then, in our <code>dashboardStats</code> array, let's replace every number value with a ternary expression and function that will convert our number if it's available:</p>
<pre><code class="lang-js">value: stats ? commafy(stats?.cases) : <span class="hljs-string">'-'</span>
</code></pre>
<p>This line checks to see if <code>stats</code> exists. If it does, we <code>commafy</code> the <code>cases</code> value. If it doesn't exist, we return a <code>-</code> to show it's unavailable.</p>
<p>Once we repeat that process for all of our numbers, we can save, reload the page, and see our human friendly numbers!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-stats-with-readable-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the statistics to be human readable</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/90f266c17815239d9d3356d9b9d660915fdc26c2">Follow along with the commit!</a></p>
<h2 id="heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</h2>
<p>Finally, we want to make sure people are staying informed and understand the last time this data was updated. Luckily, our API provides a Last Updated date for us, so let's use it!</p>
<p>At the bottom of our "tracker" <code>div</code> under <code>tracker-stats</code>, let's add the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker-last-updated"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Last Updated: { stats?.updated }
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This creates a new section where we simply include the <code>updated</code> property from our stats. And if we save and reload the page, we can see the last updated date!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding last updated to the dashboard</em></p>
<p>But how could we even understand what that number is, unless you're the computer crawling this blog post? So let's change it to a human readable format like we did with our numbers.</p>
<p>Inside of our <code>src/lib/util.js</code> file, let's add another function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * friendlyDate
 * <span class="hljs-doctag">@description </span>Takes in a date value and returns a friendly version
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">friendlyDate</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(value);
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(<span class="hljs-string">'en'</span>, {
    <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">month</span>: <span class="hljs-string">'short'</span>,
    <span class="hljs-attr">day</span>: <span class="hljs-string">'2-digit'</span>,
    <span class="hljs-attr">hour</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">minute</span>: <span class="hljs-string">'numeric'</span>
  }).format(date);
}
</code></pre>
<p>This function creates a new <code>Date</code> object, then uses the javascript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">International DateTimeFormat API</a> to convert it into a friendly readable format!</p>
<p>Once that's saved, let's import it next to our <code>commafy</code> function at the top of <code>src/pages/index.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy, friendlyDate } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then we can update our code similar to how we updated our numbers:</p>
<pre><code class="lang-jsx">Last Updated: { stats ? friendlyDate(stats?.updated) : <span class="hljs-string">'-'</span> }
</code></pre>
<p>And if we save and reload, we see it in a human readable way!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated-formatted-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the last updated date</em></p>
<p>Finally for our "last updated" should look like it fits in with the rest of the dashboard, so let's add a few more styles. Inside of our <code>_tracker.scss</code> file we were working with earlier:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-last-updated</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>And once we hit save and refresh the browser, we have our dashboard statistics with the last updated time! ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-formatted-styled.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final dashboard with formatted lasted updated date</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/408286aecb32223c8782eb1539f5563135c75dfb">Follow along with the commit!</a></p>
<h2 id="heading-what-can-i-do-next">What can I do next?</h2>
<h3 id="heading-make-the-marker-tooltip-data-human-friendly">Make the marker tooltip data human friendly</h3>
<p>Now that we have our handy <code>commafy</code> and <code>friendlyDate</code> functions, we can reuse those functions to clean up the data in our country marker popups!</p>
<h3 id="heading-use-the-fetchtracker-function-to-poll-for-updates">Use the fetchTracker function to poll for updates</h3>
<p>Inside of the <code>useTracker</code> hook we created, we exported a function called <code>fetchTracker</code>. This allows us to force a request to the API to fetch new data. To make sure our map stays current even when somebody doesn't refresh the page, we can create a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">timer</a> in javascript to regularly invoke that function to update our dashboard data.</p>
<h3 id="heading-clear-the-map-layers-before-re-adding-the-new-ones">Clear the map layers before re-adding the new ones</h3>
<p>One thing we're currently not doing is cleaning up old layers before adding a new one. The way the map is set up, it just keeps layering them on top. What we can do is before we add all of our new layers, we can clear out the old ones. <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/cad3b5a6e31a6ae090549c12e40a08fee4db4aa5">Check out this commit</a> to get started!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a> (Part 1 of this post)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to create a Coronavirus (COVID-19) Dashboard & Map App in React with Gatsby and Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world? Update: The original NovelCOVID API v1 endpoint has been de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/</link>
                <guid isPermaLink="false">66bee92588139a9746c0c5cc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 31 Mar 2020 15:16:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-mapping-app.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world?</p>
<p><strong>Update:</strong> The original NovelCOVID API v1 endpoint has been deprecated. Please update and use the following instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a></p>
<p><em>Author’s Note: This is meant to be a demo and proof of concept for putting together an impactful mapping application using real life data. For complete and accurate analysis, please make sure to use tools like <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a>. Stay home and be safe! ❤️</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</a></li>
<li><a class="post-section-overview" href="#heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</a></li>
<li><a class="post-section-overview" href="#heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</a></li>
<li><a class="post-section-overview" href="#heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</a></li>
<li><a class="post-section-overview" href="#heading-what-else-can-we-do">What else can we do?</a></li>
<li><a class="post-section-overview" href="#heading-be-safe-and-stay-informed">Be safe and stay informed</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/GryBIsfBfro" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’ll be putting together a mapping application that uses an API containing recent Coronavirus statistics and maps out the locations and impact each country is facing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus map dashboard demo</em></p>
<p>On the map, we’ll show a marker for each country with the number of confirmed cases. On top of that, we’ll include a little popup tooltip that shows more in depth information.</p>
<p>The map we’ll build will mostly look like the above, but will look a little simpler. We’ll utilize the OpenStreetMap public tileserver instead of using a custom <a target="_blank" href="https://www.mapbox.com/">Mapbox</a></p>
<p>To get started, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created to make the initial setup a little smoother. With our app bootstrapped, we’ll fetch our data and add markers to the map with our data.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven’t played with maps before, don’t be discouraged! It's not as bad as you probably think. If you’d rather start with mapping basics, you can <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a> first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>If you followed along with my previous tutorials for <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">building a Santa Tracker</a> or <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">creating a Summer Road Trip map</a>, you can follow the same steps to get started. If not, we’ll want to make sure we have the following set up:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">node</a> or <a target="_blank" href="https://yarnpkg.com/en/">yarn</a> - I'll be using yarn, but you can substitute with npm where appropriate</li>
<li><a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">Gatsby’s CLI</a> - <code>yarn global add gatsby-cli</code></li>
</ul>
<p>If you’re not sure about one of the above, you can try checking out the beginning <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">my previous tutorial</a>.</p>
<p>We’ll also want to set up a foundation for our map. We can do this by utilizing the Leaflet Gatsby Starter I put together that provides us a basic setup with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> and <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>.</p>
<pre><code class="lang-shell">gatsby new my-coronavirus-map https://github.com/colbyfayock/gatsby-starter-leaflet
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-creating-new-coronavirus-map-from-gatsby-starter.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Leaflet Gatsby app in the terminal</em></p>
<p>After that’s finished running, you can navigate to the newly created project directory and start your local development server:</p>
<pre><code class="lang-shell">cd my-coronavirus-map
yarn develop
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-starting-gatsby-development-server-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting your Gatsby app in the terminal</em></p>
<p>If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/gatsby-starter-leaflet-in-browser-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commits/master">Follow along with the commit!</a></p>
<h2 id="heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</h2>
<p>The Gatsby Starter we're using to spin up this app comes with some demo code that we don’t need here. We’ll want to make all of the changes below in the file <code>src/pages/index.js</code>, which is the homepage of our app.</p>
<p>First, let’s remove everything from the <code>mapEffect</code> function. This function is used to run code that fires when the map renders.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In src/pages/index.js</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-comment">// Get rid of everything in here</span>
}
</code></pre>
<p>We’ll also change the variable name of our <code>leafletElement</code> simply for being able to more easily understand the code as we write it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
}
</code></pre>
<p>Next, we don’t want a marker this time, so let’s remove the <code>&lt;Marker</code> component from our <code>&lt;Map</code> component:</p>
<pre><code class="lang-react">&lt;Map {...mapSettings} /&gt;
</code></pre>
<p>Now that we have those pieces cleared out, we can remove all of the following imports and variables from the top of our file:</p>
<ul>
<li>useRef</li>
<li>Marker</li>
<li>promiseToFlyTo</li>
<li>getCurrentLocation</li>
<li>gatsby_astronaut</li>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>ZOOM</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
<li>markerRef</li>
</ul>
<p>After, our map should still work, but not do anything.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/new-empty-mapping-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New mapping app with nothing going on</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/a3e9cff3949bb7ebb7cc89166c875e97b6dcb5a8">Follow along with the commit!</a></p>
<h2 id="heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</h2>
<p>For our app, we’re going to use the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. Particularly, we’re going to use the <a target="_blank" href="https://corona.lmao.ninja/countries">countries endpoint</a> to fetch the list of our countries and the stats associated with them.</p>
<p>For making requests, I personally like to use <a target="_blank" href="https://github.com/axios/axios">axios</a> as it has a nice to use API. If you want to use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch</a> or your own favorite request library, substitute that in for this step.</p>
<p>We’ll start by installing axios:</p>
<pre><code class="lang-shell">yarn add axios
</code></pre>
<p>Once that installs, remember to restart your server.</p>
<p>Import the axios package ta the top of our <code>pages/index.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre>
<p>Next we’ll actually make our request. Inside our <code>mapEffect</code> function, let’s try to make a request to the API endpoint:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://corona.lmao.ninja/v2/countries'</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Failed to fetch countries: <span class="hljs-subst">${e.message}</span>`</span>, e);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data = [] } = response;
}
</code></pre>
<p>In this snippet, we’re doing the following:</p>
<ul>
<li>Setting up a <code>response</code> variable that will allow us to store the response</li>
<li>Adding a <code>try/catch</code> block that will catch any API errors if the request fails</li>
<li>If the request is successful, we store the response in the <code>response</code> variable</li>
<li>If the request fails, we console log out the error and return out of the function so we don’t continue to run the code with a failed request</li>
<li>Once we have our response, we can destructure <code>data</code> from the response and set the default value to an empty array, as that will be the type of data we need</li>
</ul>
<p>After that’s set up, we can console log out the <code>data</code> object and we’ll see our data successfully fetched!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-location-data-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging the Coronavirus location data to the browser console</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/86bebfee4a34b9bad516879b228921cdaad55126">Follow along with the commit!</a></p>
<p><strong>Update:</strong> The previous commit includes a link to the original NovelCOVID v1 API endpoint which has now been deprecated. Please use this instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/e8f63c7ca60ec358b2edc9bc3ed8935be85b5573">See updated commit</a>.</p>
<h2 id="heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</h2>
<p>Now that we have our data, we can transform it into a geographic data format, particularly <a target="_blank" href="https://geojson.org/">GeoJSON</a>, that will allow us to interface with Leaflet.</p>
<p>Let’s start by adding this block of code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { data = [] } = response;
<span class="hljs-keyword">const</span> hasData = <span class="hljs-built_in">Array</span>.isArray(data) &amp;&amp; data.length &gt; <span class="hljs-number">0</span>;

<span class="hljs-keyword">if</span> ( !hasData ) <span class="hljs-keyword">return</span>;

<span class="hljs-keyword">const</span> geoJson = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'FeatureCollection'</span>,
  <span class="hljs-attr">features</span>: data.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { countryInfo = {} } = country;
    <span class="hljs-keyword">const</span> { lat, <span class="hljs-attr">long</span>: lng } = countryInfo;
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'Feature'</span>,
      <span class="hljs-attr">properties</span>: {
       ...country,
      },
      <span class="hljs-attr">geometry</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'Point'</span>,
        <span class="hljs-attr">coordinates</span>: [ lng, lat ]
      }
    }
  })
}
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new constant called <code>hasData</code> that checks if our <code>data</code> variable is an array and has data</li>
<li>If we don’t have data, we want to return out of the function, as we don’t want to try to add data we don’t have</li>
<li>We create a <code>geoJson</code> object that will be our GeoJSON document</li>
<li>Our document is of type <code>FeatureCollection</code> and as our <code>features</code> we loop through our dataset</li>
<li>For each country in our data, we obtain the <code>lat</code> and <code>lng</code> to create a point for our map</li>
<li>We additionally add our country data as properties so we can access it within our mapping APIs</li>
</ul>
<p>If you <code>console.log</code> this object our into your browser and copy the contents, you can paste this into geojson.io and see the location data show up correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/location-data-geojson-io.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Previewing Coronavirus location data on geojson.io</em></p>
<p>With this GeoJSON document, we'll now be able to add it to our map.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/f0da2d05cbc16783322684da7a3efaa61022f5b6">Follow along with the commit!</a></p>
<h2 id="heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</h2>
<p>We have our GeoJSON document with our location data, so let’s add it to the map.</p>
<p>Let’s start with this code block. It's a long one, but we’ll break it down piece by piece:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> geoJsonLayers = <span class="hljs-keyword">new</span> L.GeoJSON(geoJson, {
  <span class="hljs-attr">pointToLayer</span>: <span class="hljs-function">(<span class="hljs-params">feature = {}, latlng</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { properties = {} } = feature;
    <span class="hljs-keyword">let</span> updatedFormatted;
    <span class="hljs-keyword">let</span> casesString;

    <span class="hljs-keyword">const</span> {
      country,
      updated,
      cases,
      deaths,
      recovered
    } = properties

    casesString = <span class="hljs-string">`<span class="hljs-subst">${cases}</span>`</span>;

    <span class="hljs-keyword">if</span> ( cases &gt; <span class="hljs-number">1000</span> ) {
      casesString = <span class="hljs-string">`<span class="hljs-subst">${casesString.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-3</span>)}</span>k+`</span>
    }

    <span class="hljs-keyword">if</span> ( updated ) {
      updatedFormatted = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(updated).toLocaleString();
    }

    <span class="hljs-keyword">const</span> html = <span class="hljs-string">`
      &lt;span class="icon-marker"&gt;
        &lt;span class="icon-marker-tooltip"&gt;
          &lt;h2&gt;<span class="hljs-subst">${country}</span>&lt;/h2&gt;
          &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Confirmed:&lt;/strong&gt; <span class="hljs-subst">${cases}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Deaths:&lt;/strong&gt; <span class="hljs-subst">${deaths}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Recovered:&lt;/strong&gt; <span class="hljs-subst">${recovered}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Last Update:&lt;/strong&gt; <span class="hljs-subst">${updatedFormatted}</span>&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/span&gt;
        <span class="hljs-subst">${ casesString }</span>
      &lt;/span&gt;
    `</span>;

    <span class="hljs-keyword">return</span> L.marker( latlng, {
      <span class="hljs-attr">icon</span>: L.divIcon({
        <span class="hljs-attr">className</span>: <span class="hljs-string">'icon'</span>,
        html
      }),
      <span class="hljs-attr">riseOnHover</span>: <span class="hljs-literal">true</span>
    });
  }
});
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new instance of <code>L.GeoJSON</code> which will transform our GeoJSON document into something Leaflet will understand</li>
<li>Inside that instance, we define a custom <code>pointToLayer</code> function. This allows us to customize the map layer Leaflet creates for our map</li>
<li>In our function, we assign and create our datapoints that we want. Most of it is destructuring, but we format the cases count to show <code>1k+</code> instead of <code>1000</code> and a formatted date instead of the timestamp</li>
<li>We create an HTML string block which is used to define our map marker that will be added to the map. This also includes the HTML for the tooltip that will pop up when hovering over a marker</li>
<li>We return <code>L.marker</code> with our custom configuration that includes a class of <code>icon</code> for the container and our custom HTML.</li>
<li>Additionally, we add the <code>riseOnHover</code> property so when hoving over a marker, it surfaces itself above over the other markers on the map</li>
</ul>
<p>We also want to add a bit of CSS here so that we can make sure our markers show up in the map and are usable. Let’s add this snippet to our <code>assets/stylesheets/components/_map.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.icon-marker</span> {

  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">7em</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$red-800</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:hover</span> {

    <span class="hljs-selector-class">.icon-marker-tooltip</span> {
      <span class="hljs-attribute">display</span>: block;
    }

  }

}

<span class="hljs-selector-class">.icon-marker-tooltip</span> {

  <span class="hljs-attribute">display</span>: none;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">16em</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.4em</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">4em</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:before</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">bottom</span>: -.<span class="hljs-number">6em</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
    <span class="hljs-attribute">transform</span>: rotate(<span class="hljs-number">45deg</span>);
    <span class="hljs-attribute">margin-left</span>: -.<span class="hljs-number">7em</span>;
  }

  <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.2</span>;
    <span class="hljs-attribute">margin-bottom</span>: .<span class="hljs-number">1em</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-tag">h3</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2em</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">1em</span> <span class="hljs-number">0</span>;
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-100</span>;
  }

  <span class="hljs-selector-tag">ul</span>,
  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
  }

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">6em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>What we’re doing:</p>
<ul>
<li>We create our round markers using the <code>.icon-marker</code> class and set up our <code>.icon-marker-tooltip</code> class to show up when hovered over</li>
<li>Our <code>.icon-marker-tooltip</code> class is hidden by default, as it’s our tooltip, but we position it absolutely to appear over top of our marker and formatted the way we want it</li>
</ul>
<p>And finally, once we have our <code>geoJsonLayers</code> created with our styling added, we can add it to the map!</p>
<pre><code>geoJsonLayers.addTo(map)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data</em></p>
<p>Now you might be wondering why it doesn't appear to be centering properly. Go ahead and change the <code>LOCATION</code> variable at the top of the <code>index.js</code> file to:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> LOCATION = {
  <span class="hljs-attr">lat</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lng</span>: <span class="hljs-number">0</span>
};
</code></pre>
<p>Once that’s set, when the page reloads, the map should be centered in the middle of the world!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data-centered-tooltip.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data centered with a tooltip</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/49c78e4ef3e98c974fab7bca10b6f8f7578b42c2">Follow along with the commit!</a></p>
<h2 id="heading-yay-we-did-it">Yay, we did it! ?</h2>
<p>If you followed along, you now have created your own Coronavirus map dashboard that gives some quick stats about the cases around the world.</p>
<p>Take what you learned and run with it. You can apply this to any other type of data that you can imagine.</p>
<h2 id="heading-what-else-can-we-do">What else can we do?</h2>
<h3 id="heading-add-more-styles-and-a-custom-basemap">Add more styles and a custom basemap</h3>
<p>In my original demo, I set up a custom basemap using <a target="_blank" href="https://mapbox.com/">Mapbox</a> that allows me to have a dark background making the markers easier to see.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/mapbox-studio-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new basemap in Mapbox Studio</em></p>
<p>Mapbox is great and has a nice free tier if you’re interested in getting started.</p>
<p>Once you have a Mapbox account, you can even <a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">copy the style</a> I used and make it your own.</p>
<p><a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">Basic Dark Mapbox Theme</a></p>
<p>To learn how to integrate it, you can try to check out the source code of <a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">my original demo</a>:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">https://github.com/colbyfayock/coronavirus-map-dashboard</a></p>
<h3 id="heading-add-overview-dashboard-stats">Add overview dashboard stats</h3>
<p>Dashboards with maps like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University app</a> allows us to see more than a look on the map, but a glimpse at quick stats about the cases around the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/johns-hopkins-coronavirus-map-march-29.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Johns Hopkins University Coronavirus Map Dashboard - March 29, 2020</em></p>
<p>The <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a> has more endpoints like <code>/all</code> that provide a few global stats.</p>
<h2 id="heading-be-safe-and-stay-informed">Be safe and stay informed</h2>
<p>I want to reiterate that you should make sure you're staying up to date using official sources for information, such as the Johns Hopkins University dashboard. Though the data should be reliable, it should also be considered a proof of concept for building a map and referencing, but shouldn't be considered for any kind of statistical analysis.</p>
<p>Please take care of yourself during these times. We're all in this together! ❤️</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Inside the Hack for Wuhan Hackathon – How Developers Fought COVID-19 ]]>
                </title>
                <description>
                    <![CDATA[ The Chinese New Year in 2020 was one of the saddest Chinese New Years in recent memory. After the sudden outbreak of the COVID-19 virus, the city pressed pause on all celebrations. And now – even as the pandemic lets up in China – schools remain clos... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/wuhan-hackathon/</link>
                <guid isPermaLink="false">66d85ab229e30bc0ad477652</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hackathon ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 24 Mar 2020 23:05:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/image-38-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Chinese New Year in 2020 was one of the saddest Chinese New Years in recent memory. After the sudden outbreak of the COVID-19 virus, the city pressed pause on all celebrations.</p>
<p>And now – even as the pandemic lets up in China – schools remain closed. Most of the shops are still closed. People still can’t go out and enjoy the spring.</p>
<p>In this global public health crisis, it's not just front line medical staff taking action. Other people are producing masks and protective equipment, transporting daily supplies, and providing psychological assistance to people in affected areas.</p>
<p>And developers are jumping into action, too.</p>
<h2 id="heading-the-hack-for-wuhan-hackathon"><strong>The </strong>Hack for Wuhan<strong> H</strong>ackathon<em>**</em></h2>
<p>The <a target="_blank" href="https://github.com/wuhan2020">wuhan2020 open source community</a> planned a big <a target="_blank" href="https://github.com/wuhan2020">hackathon</a>. The theme: open source collaboration to tackle the challenges behind the epidemic.</p>
<p>Together, they encouraged developers to take advantage of their own technology to support this new smokeless war.</p>
<p>wuhan2020 is a group of independent developers who write code to aggregate and analyze epidemic data. They use this to predict the spread of the virus and figure out where to send medical supplies.</p>
<p>Since wuhan2020 was created in January, it has already attracted more than 3,000 volunteers from different countries.</p>
<p>They reached out to freeCodeCamp asking if we'd be interested in helping support their upcoming hackathon. I also discovered that the leader of freeCodeCamp's Chengdu study group, Shui Ge, was one of wuhan2020's core developers.</p>
<h2 id="heading-how-freecodecamp-got-involved">How freeCodeCamp Got Involved</h2>
<p>freeCodeCamp joined the hackathon organization team as a cohost. Several of our contributors helped plan the competition, served as judges, and maintained the <a target="_blank" href="https://github.com/wuhan2020/Hackathon">GitHub repository</a>.</p>
<p>It took only 20 days from initial idea to hosting the hackathon itself.</p>
<p>Here is some quick data about the event:</p>
<ul>
<li>More than 50 volunteers hosted the competition</li>
<li>902 contestants from 33 countries signed up</li>
<li>33 teams entered the preliminary round. 12 teams reached the final round. And 8 teams won the grand prize.</li>
<li>4 companies provided technical resources for the competition, including IBM Developer, Agora.io, Tencent Serverless,  and Amazon Web Services.</li>
<li>45 industry professionals around the world provided guidance, such as Connie Chan at the Andreessen Horowitz Venture Capital firm, former Alibaba CTO Zhuang Ziming, and Eva Woo from The Stanford Center on Philanthropy and Civil Society (PACS)</li>
<li>48 media published articles about the hackathon that more than 700,000 people read</li>
</ul>
<p><img src="https://chinese.freecodecamp.org/news/content/images/2020/03/image-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Even more data. Yes - this is in Chinese but if you can't read Chinese you may be able to guess the meaning from the icons :)</em></p>
<h2 id="heading-hackathon-themes"><strong>Hackathon </strong>Theme<strong>s</strong></h2>
<p>The overall theme of the hackathon was: use open source software to solve the social challenges behind the epidemic. </p>
<h2 id="heading-introducing-some-of-the-winning-projects"><strong>Introduc</strong>ing Some of the Winning Projects</h2>
<p>The 12 finalists started their live demos online, and judges were able to comment online as well.</p>
<h3 id="heading-finalist-a-one-stop-open-platform-for-epidemic-data"><strong>Finalist: A </strong>One-stop<strong> O</strong>pen<strong> P</strong>latform for<strong> E</strong>pidemic<strong> D</strong>ata<em>**</em></h3>
<p>This open platform helps researchers efficiently collect, label, and analyze outbreak data.</p>
<p>Lots of official agencies and health commissions report fine-grained epidemic data. But the data formats are often incompatible, and require humans to interpret them. This makes it impossible to use crawlers to automatically crawl and structure the data. You have to introduce skilled manual labor.</p>
<p>So how do you collect data efficiently with as little labor as possible?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-149.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This project adopts an open source collaboration method, bringing all people interested in the data to this platform. Then the platform helps people structure and label the data.</p>
<p>Once that's done, the platform makes the data available through a public API. Scientists and developers can build other tools on top of this API.</p>
<h3 id="heading-autovax"><strong>autovax</strong></h3>
<p>Autovax is a web application that allows a vaccine and other treatment drugs to be automatically generated from the virus genome and virus genes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-151.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>A researcher from Harvard is developing this to help with COVID-19.</p>
<h3 id="heading-city-hero"><strong>City Hero</strong></h3>
<p>In this educational game, you can choose a profession – such as doctor or nurse – to experience their life during the pandemic. This helps players understand the people involved in the aid effort, and the difficult choices they face.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-148.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-path-forward">The Path Forward</h2>
<p>The Hack for Wuhan hackathon was not just a challenge for the contestants, but also a challenge for the organization team. We planned and executed everything in just 20 days, and helped 900 developers participate.</p>
<p>I want to thank everyone involved. And thank you for reading this hackathon report.</p>
<p>I hope you all will stay safe, and that we can all embrace spring as soon as it's safe.</p>
<p>If you are interested in learning more about these projects, or participating in our next hackathon, you can contact me on WeChat at fcczhongguo, or <a target="_blank" href="https://twitter.com/miyaliu666">on Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
