Using the Google Maps JavaScript API in a React Project 🗺

Matthew Thorry
Frontend Weekly
Published in
7 min readSep 27, 2017

Checkout the completed app here. Give me a clap if you like what you see! 👏🏽

If you are interested in a more straightforward approach to adding a Google Map to your latest project, check out my other article “Simplified Google Maps API in a React App

In my last project, which I talked about a bit here, I imported events from an outside API and when you clicked on the event, you were able to see a Google Map showing you the location of the event. It was very easy to implement and it made the whole page look much more professional! 👨🏽‍💻

Cut to now, I’m currently building an app using React and I thought it would be great to use the Google Maps API again except it was not easy at all this time. 😤 For some reason, Google Maps and React.js just do not mix well! Here’s how to do it so you don’t have the same problems I did!

As a former Earth Science Teacher, I can’t help but think of tools that would be useful for the classroom so I made an Earthquake Mapper App using the USGS Earthquakes API. I wanted to make a visually compelling map that easily points out patterns in seismic activity.

Here’s my Earthquakes Mapper App thus far. You can see the locations of earthquakes all around the world and filter them based on magnitude or date. I also used the Heatmap overlay. Apologies for the lack of formatting, functionality before beauty!

Step One: Install NPM module

The first thing you should do if you want to use the Google Maps API in your project is to not follow the documentation Google provides. This works well in basic HTML but React.js uses a “virtual DOM” so the implementation of Google Maps is also different. The documentation here, from Fullstack React, is much more helpful! Use that documentation in conjunction with this and you’ll be golden 👌🏽

Skip the “Loading a Google-based Component” section and instead start by installing the google-maps-react npm module. Install the library by using npm install --save google-maps-react. This install gives you all the functionality of the Google Maps API without the headache.

UPDATE!!! Due to an update to React, I’ve been having issues getting things to work. Check your package.json file and make sure you DO NOT have the most up to date version of React as well as a devDependency:

{
"name": "earthquakesreact",
"version": "0.1.0",
"private": true,
"dependencies": {
"google-maps-react": "^1.1.0",
"react": "^15.6.1", ///MAKE SURE YOU DON'T HAVE V.16
"react-dom": "^15.6.1", ///MAKE SURE YOU DON'T HAVE V.16
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.13"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"google-maps": "^3.2.1" //GOOGLEMAPS HERE TOO
}
}

Step Two: Decide who the parent of the Map is

Now you need to determine where the map is going to be placed. For my project, I have the tree shown at left.

  • EarthquakesContainer is the child of App.
  • EarthquakesMap is the child of EarthquakesContainer and sibling of EarthquakesForm
  • EarthquakesList is currently the child of EarthquakesContainer with EarthquakesItem as the child of List. I plan on changing this and only having the map.

Since my Map is the child of the EarthquakesContainer I need to paste my first bit of Google API code into the EarthquakesContainer component.

In a normal React project, you would export each of your components so they can communicate with one another but we also want them to communicate with Google Maps so we’re going to wrap our export in the Google Maps API.

Usual export: export default EarthquakesContainer

With Google Maps:

//import the GoogleApiWrapper
import {GoogleApiWrapper} from 'google-maps-react'
//pass the google info as props to the Map
<EarthquakesMap google={this.props.google} />
//export the container WITHIN the GoogleApiWrapper
export default GoogleApiWrapper({
apiKey: 'YO KEY!',
libraries: ['visualization']
})(EarthquakesContainer)

Now our EarthquakesContainer is in communication with the Google Maps API and we’re ready to roll! When you do this, you need to get an API key from Google, which is easy to do, and paste your key in quotes in place of YO KEY! . I also included the visualization library so I could use the Heatmap layer.

Step Three: Write Map functionality

Put all your map info into your Map component 😎 ! This part is where it can get a little complicated, depending on what you want your map to do.

//import React and ReactDOM which we need to mount the map
import React, { Component } from 'react';
import ReactDOM from 'react-dom'

Next you do a normal export of your component. Then I check to see if the map needs updating by checking the previous props with the current props. This renders the map on page load or after a search. It calls the loadMap() function.

export default class EarthquakesMap extends Component {
componentDidUpdate(prevProps, prevState) {
if (prevProps.google !== this.props.google || prevProps.quakes !== this.props.quakes) {
this.loadMap();
}
}

The loadMap() function is where the map logic lives. I have the full code at the bottom of this section if you’d like to look for reference! First, check to make sure the Google API is working by checking for the google props and then sets those to constants. I’m using the latest JavaScript syntax (ES6), so no more var! I also created a mapConfig object with all the properties for my map.

Since I want to see worldwide earthquakes, I center my map on the middle of the Pacific Ocean (hello, Ring of Fire) with a zoom of 2 and terrain. Cooperative gestureHandling makes it so the map does not zoom in/out when scrolled over.

I then create a new map (which is a Google property) with my node (it finds a ReactDOM node with a ref of map. This is why we needed to import 'react-dom'.

After that I iterated through my earthquake data and added each to my heatmapData array. Every point on Google Map needs a latitude and longitude which you create by setting a location key equal to new google.maps.LatLng(lat, long). I also included a weight key to make larger magnitude earthquakes count for more on the Heatmap. This means a magnitude of 6 or greater will appear 3 times heavier than an earthquake with magnitude smaller than 5.

Then, to add a marker for each earthquake, I needed to utilize new google.maps.Marker which accepts an object where you can specify properties. position is the latitude and longitude of the earthquake. This is different from before because that was for the HEATMAP, which makes the map different colors. map is the map you are appending your markers to. title is the title of the marker and icon is the icon that appears on the screen.

Lastly, I wanted to make it so you could click on the marker and have an info box open, so I included new google.maps.InfoWindow with all the specific info for that earthquake. Then I added an eventlistener to the marker and used the function infoWindow.open(this.map, marker). Now when you click on a marker, the infoWindow for that earthquake will open.

Last part is the add the heatmap layer with new google.maps.visualization.Heatmaplayer which I populate with the heatmapData array from before. The radius is the size of each heatmap circle on the map. I used 35 because of how far out the map is zoomed. Then all you do is append your Heatmaplayer to your map with heatmap.setMap(this.map) where heatmap is the const I set my heatmap layer to and this.map being the Google Map I created.

loadMap() {
if (this.props && this.props.google) {
const {google} = this.props;
const maps = google.maps;
const mapRef = this.refs.map;
const node = ReactDOM.findDOMNode(mapRef);
const mapConfig = Object.assign({}, {
center: {lat: 0, lng: 180},
zoom: 2,
gestureHandling: "cooperative",
mapTypeId: 'terrain'
})
this.map = new maps.Map(node, mapConfig);
var heatmapData = [];
this.props.quakes.map( (quake) => {
let mag
if (quake.properties.mag < 5) { mag = 3 } else if (quake.properties.mag > 6) {mag = 10} else {mag = 5}
heatmapData.push({
location: new google.maps.LatLng(quake.geometry.coordinates[1], quake.geometry.coordinates[0]),
weight: mag
})
const marker = new google.maps.Marker({
position: {lat: quake.geometry.coordinates[1], lng: quake.geometry.coordinates[0]},
map: this.map,
title: quake.properties.title,
icon: {
url: //include a URL for specific icon
}
});
var infowindow = new google.maps.InfoWindow({
content: `<h3>${quake.properties.title}</h3>
<h4>${(new Date(quake.properties.time)).toDateString()}
at depth of ${quake.geometry.coordinates[2]} km</h4>`
});
marker.addListener('click', function() {
infowindow.open(this.map, marker);
});
})
var heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
radius: 35
});
heatmap.setMap(this.map);
}
}

All that’s left to do is render the map! You must specify the size of the map otherwise it won’t work. Below I created a style object which I then used to set my div style to. I also included loading map... so when the map isn’t populated yet, the user gets a message.

render() {
const style = {
width: '100vw',
height: '75vh'
}
return (
<div ref="map" style={style}>
loading map...
</div>
)

And that’s it! You’re ready to rock!

If you enjoyed the article, I’d love for you to let me know by giving a clap! 👏🏽

I am currently an assistant instructor at the nonprofit C4Q which helps underrepresented people learn to code and break into tech. You can see more of my code on GitHub or learn more about me on my personal site.

--

--

Matthew Thorry
Frontend Weekly

Former science teacher 👨🏽‍🏫 turned software engineer 👨🏽‍💻 More at: thorry.io