@react-google-maps/api thoughts (pt.2)
Tags: react, google, maps, markers
Published: 2020-05-11 06:02:19

On my last blog I went over my favorite react component setup for using @react-google-maps/api. I sang the blues about having to read multiple docs just to get the map component set up which motivated me to the point of blogging. After doing so, I realized there is more to the story than just rendering a map to a webpage, so much more! 

While I won't be able to cover my entire mapping adventure I wanted to at least talk about a very important part of maps, markers. This blog will be useful to anyone who has the initial google map component set up and rendering to their web application. If that's not you, and you'd like it to be, check out my previous post "@react-google-maps/api thoughts (pt.1)" and that should get you up and running. Then come back here to add some sweet markers to your shiny new map.

In this post I'll cover these three things (almost simultaneously):
     1. Adding a marker to a map
     2. Clearing a map of all markers
     3. A few drops of useful code for future killer features

Let's get to it.

To utilize a marker with @react-google-maps/api we'll have to import the component at the top of our page so make sure you have destructured Marker as well:
```
   import { GoogleMap, useLoadScript, Marker } from '@react-google-maps/api'
```
Next we'll add need to add three things to our state: an id for the markers, an array for the markers, and a boolean, drawMarker, so we can know if we are drawing markers on the map or not.
```
   const [ id, setId ] = useState(0);
   const [ markers, setMarkers ] = useState([]);
   const [ drawMarker, setDrawMarker ] = useState(false);
```
Let me pause here for a short disclaimer...

My goal here is to provide a quick and dirty guide to rendering a map with markers all while understanding some simple tools for future develop of even more interesting features. 

I normally would not recommend building out one solitary component to hold all of these features/functionalities. However, in the interest of sharing a smidge of insight, that's what we'll be doing here.

Well... I feel better. Let's carry on.

Next we need some buttons. These buttons will eventually allow us to add markers to our map and remove markers from our map. If we are going to add buttons we will have to wrap our current <GoogleMap> component in a <div>. Then underneath the </GoogleMap>, but inside of the </div>, we'll add some buttons.
```
     <div>
      <GoogleMap
      {/* a bunch of stuff we added from the last blog */}
      </GoogleMap>
      <button
        type="button"
        style={{backgroundColor: drawMarker ? "green" : null}}
        onClick={()=>{setDrawMarker(()=>!drawMarker)}}
      >ADD & DRAG</button>
      <button
        type="button"
        onClick={()=>setMarkers([])}
      >CLEAR MAP</button>
    </div>
```
At this point we should still have a google map displayed on http://localhost:3000/ as well as two new buttons. The ADD & DRAG button should even change colors when it is clicked on. 

Let's pause for a worthy cause to understand where we are headed. When ADD & DRAG is green, which happens when drawMarker is set to true, we will soon be able to add markers with the GoogleMap's onClick functionality. When ADD & DRAG's background is null, the map will operate as normal. The background color of the button is dependent on truthiness of drawMarkers. We will write out the function to actually add the markers to the map next. The second button simply clears all (theoretical) markers off of the map by setting the markers state to an empty array.

Here comes the big kahuna. First we'll add an onClick function to the map which can come in handy for just about any future features you might want to add. Honestly this next console.log is why I wanted to write this entire blog in the first place. It took me a while to find this guy and once I did I started to realize some of the amazing potential that a map can offer. Put your seat belts on people:
```
      <GoogleMap
        {/* some other code we wrote inside of this component... */}
        onClick={(e)=> console.log(e.latLng.toJSON())}
      >
```
Open your console and start clicking on your map! As you can see, when you click anywhere on the map it logs the actual latitude and longitude to the console! It is not weird mouse coordinates that you have to convert, it is not a random click event, our app is logging specific, real, live, actual coordinates! So totally awesome.

Now, gather yourself and let's use these coordinates to add markers by their latitude and longitude. 

To wrap this up we need write out a function that adds markers to our markers array in our state, rewrite our onClick to create a new marker only if our drawMarker is true, and then map over all of the markers to render them to the page.

Final step 1 of 3 - Add marker to Map
```
  // add marker to Map
  const addMarker = (coords) => {
    setId((id)=>id+1);
    setMarkers((markers) => markers.concat([{coords, id}]) )
  }
```

Final step 2 of 3 - Rewrite GoogleMap's onClick
```
   onClick={(e)=> drawMarker ? addMarker(e.latLng.toJSON()) : null}
```

Final step 2 of 3 - iterate over markers and create a Marker component with each one
```
    <GoogleMap>...{/* this goes inside of your GoogleMap component*/}
      {markers ? (
        markers.map((marker) => {
          return (
            <Marker
              key={marker.id}
              draggable={drawMarker}
              position={marker.coords}
              onDragEnd={e => marker.coords = e.latLng.toJSON()}
            />
          )
        })
      ) : null }
    </GoogleMap>
```
That was a lot of code to wrap up, but we are really just utilizing basic JavaScript to render these markers. The power of knowing that we have actual latitude and longitude coordinates at every click of a mouse is amazing to me. Go forth and map-make to your hearts content. See if you can remove a marker by its id, reset the center of the map (hint: myMap.center.toJSON()), or add info windows to the markers. There are some really cool capabilities in this library and hopefully these two blog posts will help you on your own mapping adventure. Best of luck!