Data visualizations have gotten a lot more popular over the last 5-10 years with the rise of software like D3, Tableau, and infographics. Maps just might be the original data visualization. In fact, maps are so commonplace that we don’t often see them in the same realm as the newer/shinier forms of data visualization. But like other data visualizations, they are just a representation of data (spatial in this case). For almost every web application that works with spatial data, maps are essential.

There are a variety of libraries for building maps in React-based applications. This tutorial will focus on building a simple google map using React, Google Sheets, and the very powerful (and well-maintained) google-map-react library.

In my previous article, I covered how to make a simple React app that pulled data in from a Google Sheet using the sheets API. We’ll be building upon that to make a simple map using that same data.

Let’s Build a Map of Sweet Views

A little backstory on the demo app we’ll build: the San Francisco Bay Area is full of hills. On some of these hills, you can find public spaces with incredible views of the ocean, city, bay, and various neighborhoods. After having your head in a computer all day, there’s no better way to zoom out, admire your gorgeous and expensive city, and think about how small you are. But if you just moved to the area, you might not know where to find these great views. Hence the need for a map!

Here are some of my favorite views in the bay area and the data we’ll be using for this app:

id name lat lng 1 Grandview Park 37.7564084 -122.4717396 2 Hawk Hill 37.8254957 -122.4995417 3 Grizzly Peak 37.8822385 -122.2336546 4 Bernal Heights 37.7431498 -122.4152257 5 Tank Hill 37.7599703 -122.4477785

Install Dependencies and Set Required Values

To add a map to our original project (clone here) , we first need to install google-map-react:

$ yarn add google-map-react

With that done, let’s create a MapAndMarkers component that we’ll call in our main App component and pass some props to.

Let’s first call the component in our main App.js file (and we’ll build it after).

import MapAndMarkers from './MapAndMarkers.js'

The GoogleMapReact component (from google-map-react) has a few required props in order to make a map. Two of these props are center and zoom. These are, logically, the minimum for having a map. The map needs to know which tiles (map images) to load and center on and how far to zoom in.

Let’s have these live in our parent App’s state. We can change these state values later (with user events) to have our components re-render. So state will now look like this in the component:

this.state = { items:[], center: { lat: 37.8254957, lng: -122.4995417 }, zoom: 10, };

Google maps zoom values must range between 1 (the whole world) and 20 (down to specific buildings). These center coordinates are located roughly in the San Francisco Bay. This zoom level of 10 shows the general Bay Area. Now pass these to the MapAndMarkers component:

<MapAndMarkers markers={this.state.items} zoom={this.state.zoom} center={this.state.center} />

Create MapAndMarkers Component

We are now going to create a very simple MapAndMarkers component. I’ll put comments in the code to explain what is happening:

import React, { Component } from "react"; import GoogleMapReact from "google-map-react"; // This is the primary map parent component /* A very very simple map marker */ const Marker = ({ name }) => <div> {name} </div>; export default class MapAndMarkers extends Component { constructor(props) { super(props); } render() { const { markers } = this.props; // Destructuring our props to get the google sheets data // map over the array of markers to create a set of mapmarkers for our map to display. Map markers, as you can imagine, need to have lat and lng props in order for the parent map to know where to put them. let mapmarkers = markers.map((marker, index) => { return ( <Marker key={marker.id} lat={marker.lat} lng={marker.lng} name={marker.name} /> ); }); /* Call the GoogleMapReact component and pass it the api keys and google maps version in the bootstrapURLKeys prop. Pass it the center and zoom from props. The array of mapmarkers is given to the GoogleMapReact component (as its child) to be rendered on the map */ return ( <div style={{ height: "100vh" }}> <GoogleMapReact bootstrapURLKeys={{ key: "yourapikey", // get a key here: https://developers.google.com/maps/documentation/javascript/get-api-key v: "3.32" }} center={this.props.center} zoom={this.props.zoom} > {mapmarkers} // array of map marker divs </GoogleMapReact> </div> ); } }

This component will render a map and markers that looks something like this:

Pretty ugly, right? The only reason I did this was to show that google-map-react can render any component on a map. It can be a map pin/marker, a custom animation, shapes, or just plain text like above. This library gives the React developer a lot of freedom to make maps in a component-driven way. We are simply rendering components on a map. Other mapping libraries (e.g. tomchentw/react-google-maps) might give you more HOCs and built-in methods to play with, but I found they didn’t follow the React small-composable-components paradigm as much.

Make Prettier Map Markers

Let’s make our map markers more marker-like with some icons. Feather icons is a well-maintained and lightweight icon library. React-feather offers feather icons as components. Let’s use that.

$ yarn add react-feather

We import the feather map pin icon simply enough:

$ import { MapPin } from 'react-feather';

And change our marker to this:

const Marker = ({name}) => ( <div><MapPin />{name}</div> );

Getting warmer:

How About a Tooltip?

A tooltip would go a long ways toward making these markers look a bit more map-like.

There are dozens of React tooltip libraries out there. They vary greatly in terms of their APIs and maintenance. As with any library, I recommend some caution and research before adding a tooltip library to your project. There are few things more frustrating than finding your issue is the same issue that many other have (and the maintainer hasn’t accepted pull requests in many months). Rc-tooltip is a well-maintained tooltip library and has a straightforward and robust API.

Implementing the tooltip is quite straightforward:

$ yarn add react-tooltip

import Tooltip from "rc-tooltip";<br> import '../node_modules/rc-tooltip/assets/bootstrap.css'; // basic integration of Tooltip with the previous Marker const Marker = ({ name }) => <div style={{ height: "50px", width: "50px" }}> <Tooltip placement="top" // You can choose whichever side you want it to show on animation="zoom" // A smooth zoomy animation when it opens overlay={ <span> {name} // What shows up in the tooltip </span> } > <span> <MapPin /></span> // Hovering on the MapPin will cue the pop up </Tooltip> </div>;

This gives us clean, animated tooltips for our map icons.

We’ve now covered the basics of rendering map points on a Google map and giving them cute icons and tooltips. There’s so much more we can do, of course. Future tutorials will delve into responding to user events like hovering on the map and opening and closing our tooltips using state and props.

The code for this tutorial is here: https://github.com/kpennell/google-sheets-map