Project 59 of 100 - React Wildfire Tracker
Tags: react, 100daysofcode, javascript
Published: 2021-03-13 18:33:37

*Hey! I'm on a mission to make 100 React.js projects ending March 31st. Please follow my dev.to profile or my [twitter](https://www.twitter.com/jwhubert91) for updates and feel free to reach out if you have questions. Thanks for your support!*

Link to the deployed project: [Link](https://100-react-projects-day-59-fire-tracker.netlify.app/)
Link to the repo: [github](https://github.com/jwhubert91/100daysofreact/tree/master/day-59-wildfire-tracker)

This was a quick video, and I actually had a blast doing it. I'm sometimes not the biggest fan of Brad Traversy's long form videos because I don't feel I absorb much with code-along tutorials, but shorter videos covering material you *mostly* know and want practice with are excellent and [his video creating a React Wildfire Tracker](https://www.youtube.com/watch?v=ontX4zfVqK8&ab_channel=TraversyMedia) fit the bill for a late Saturday night coding session.

The data for this website comes from NASA. This was my first time using their API so that was a pleasure. We made use of their [Events API](https://eonet.sci.gsfc.nasa.gov/docs/v2.1#eventsAPI) which tracks natural events going on in the world. This was also my first app using Google Maps. In previous projects I had opted for Mapbox because it was free, but I do enjoy Google Maps' bright color scheme that feels like a real map (vs an app) and easy navigation. To display the map in React I used the `google-map-react` npm package. 

Other npm packages I made use of included `LoaderSpinner` for an animated spinner on loading screens, the Iconify icon package at `@iconify/react` and specifically their Material Design icon library at `@iconify/icons-mdi`. I also used `dotenv` to save sensitive API info in process variables. I accidentally forgot to put the Header in my components folder. Forgive me for it.

First, in our `App` component we import `useState` and `useEffect` from the React package. We then create two pieces of state- `loading` and `eventData`. Loading will be a boolean that indicates whether the data is being fetched. We will use it to display a loading spinner if it is true. `eventData` will be an empty array until our fetch method returns data. We'll use `useEffect` to fetch data from the API on page load.

```JS
import React,{useState,useEffect} from 'react'
import LoaderSpinner from './components/LoaderSpinner'
import Map from './components/Map'
import Header from './Header'

function App() {
  const [eventData,setEventData] = useState([])
  const [loading,setLoading] = useState(false)

  useEffect(() => {
    const fetchEvents = async () => {
      setLoading(true)
      const res = await fetch('https://eonet.sci.gsfc.nasa.gov/api/v2.1/events')
      const {events} = await res.json()
      
      setEventData(events)
      setLoading(false)
    }

    fetchEvents()

    console.log(eventData)
  }, [])

  return (
    <div>
      <Header />
      {!loading ? <Map eventData={eventData} /> : <LoaderSpinner />}
    </div>
  );
}

export default App;

```

`LoaderSpinner` is a separate component that uses the `react-loader-spinner` package. According to [the documentation](https://www.npmjs.com/package/react-loader-spinner) you'll need to manually load in the CSS. I chose the ThreeDots type variant because I thought it looked the most professional.

```JS
import React from 'react'
import Loader from 'react-loader-spinner'
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css'

const LoaderSpinner = () => {
  return (
    <div className='loader-spinner'>
      <Loader 
        type="ThreeDots"
        color="#000000"
        height={100}
        width={100}
      />
      <h1>Fetching Fire Data...</h1>
    </div>
  )
}

export default LoaderSpinner
```

In the Map component, we use `GoogleMapReact` to render a Google Map. You'll need to give the map component a center point in coordinates, a zoom level and your API key. Mine is stored in a `.env` file. I also gave the `center` prop a set of `defaultProps` with the coordinates. 

The Google Map component is pretty neat because you can give it children and if the children have `lat` and `lng` props the map will put them in the right place on the map.

We also provide an `onClick` handler to the `LocationMarker` component so that when a fire icon is clicked we set the `locationInfo` state to an object with data relevant to the fire.

```JS
import React,{useState} from 'react'
import GoogleMapReact from 'google-map-react'
import LocationMarker from './LocationMarker'
import LocationInfoBox from './LocationInfoBox'

const Map = ({eventData,center,zoom}) => {
  const [locationInfo,setLocationInfo] = useState(null)
  
  const markers = eventData.map(ev => {
    if (ev.categories[0].id === 8) {
      return (
        <LocationMarker 
          key={ev.id} 
          lat={ev.geometries[0].coordinates[1]} 
          lng={ev.geometries[0].coordinates[0]} 
          onClick={() => {setLocationInfo({
            id: ev.id,
            title: ev.title,
            lat: ev.geometries[0].coordinates[1],
            long: ev.geometries[0].coordinates[0]
          })}}
        />)
    }
    return null
  })

  return (
    <div className='map'>
      <GoogleMapReact
        bootstrapURLKeys={{key: process.env.REACT_APP_GOOGLE_API_KEY}}
        defaultCenter={center}
        defaultZoom={zoom}
      >
        {markers}
      </GoogleMapReact>
      {locationInfo && <LocationInfoBox info={locationInfo} />}
    </div>
  )
}

Map.defaultProps = {
  center: {
    lat: 42.3265,
    lng: -122.8756
  },
  zoom: 6
}

export default Map
```

This is the kind of project I love because it has immediate real world application. Hope you like it!