Easy google maps setup using google maps api in React

Scott Picquerey
inato
Published in
5 min readJun 22, 2023
Photo by henry perks on Unsplash

Pre-requisite

Before going through this article, it is primordial that you have a setup google maps api key. Here is a link to the associated documentation:

https://developers.google.com/maps/documentation/javascript/get-api-key

Context

For a recent project at Inato, we wanted to display a map with classic features such as pin point of interest, clusters, zoom on locations…

Our product being based on React and Typescript, we used the following tools to build a consistent solution:

  • Google Clouds Platform
  • @googlemaps/react-wrapper
  • @googlemaps/markerclusterer

In this article, you will find a complete walkthrough to help you:

  1. Display a map
  2. Add marker locations
  3. Add marker clusters

Display a map

To start this project, we need to display a working map in our App.

As a pre-requisite, we need to install the following:

yarn add @googlemaps/react-wrapper
yarn add -D @types/google.maps

First things first, we want to build a Wrapper that will allow us to authenticate to google maps and hence, load our map successfully.

import React from "react";
import { Wrapper } from "@googlemaps/react-wrapper";

export const GoogleMapsWrapper = ({
children,
}: {
children: React.ReactNode;
}) => {
// Ideally we want the apiKey to be fetch from an environment variable
const apiKey = "yourApiKey";

if (!apiKey) {
return <div>Cannot display the map: google maps api key missing</div>;
}

return <Wrapper apiKey={apiKey}>{children}</Wrapper>;
};

Let’s now use, in the component that will need to display the map, our new GoogleMapsWrapper by passing the Map component as its child.

Nb: Another possible solution, is to put the GoogleMapsWrapper at the App level. I don’t recommend it though, because you might not want to have your whole app not rendering if you dont have a valid api key.

export const MapComponent = () => (
<GoogleMapsWrapper>
<div>Insert Map component here<div/>
</GoogleMapsWrapper>
);

Everything is now set to welcome our GoogleMaps component, let’s build it!

import React, { useEffect, useRef } from "react";

const DEFAULT_CENTER = { lat: 48.8566, lng: 2.3522 };
const DEFAULT_ZOOM = 7;

export const GoogleMaps = () => {
const ref = useRef<HTMLDivElement | null>(null);

useEffect(() => {
// Display the map
if (ref.current) {
new window.google.maps.Map(ref.current, {
center: DEFAULT_CENTER,
zoom: DEFAULT_ZOOM,
});
}
}, [ref]);

return (
<div
ref={ref}
style={{ width: "1000px", height: "700px" }}
/>
);
};

Nb: Do not forget to pass a width and a height to the map or it won’t be displayed !

Finally, use the GoogleMaps component in the MapComponent:

export const MapComponent = () => (
<GoogleMapsWrapper>
<GoogleMaps />
</GoogleMapsWrapper>
);

Congratulations, we now have a map rendered in the component 🎉

Add marker locations

Now that we have a map displayed, we would like to display some markers on it. For the sake of the example, let’s suppose that we have some locations defined by their longitude and latitude.

To start, we can write a function addSingleMarkers. It will be used to create, for each given location, an instance of google.maps.Marker. These markers will be passed to our map to load the locations.

export const addSingleMarkers = ({
locations,
map,
}: {
locations: ReadonlyArray<google.maps.LatLngLiteral>;
map: google.maps.Map | null | undefined;
}) =>
locations.map(
position =>
new google.maps.Marker({
position,
map,
}),
);

Nb: google.maps.LatLngLiteral is just an object {lat: number; lng: number}

The next step is to display the markers when rendering the map. To do it, we can do two things:

  1. add a new prop locations in the component, passed by the parent
  2. call the freshly created method addSingleMarkers in the useEffect and pass it the locations. It will run through each locations and display markers on the map on render.
import React, { useCallback, useEffect, useRef } from "react";
import { addSingleMarkers } from "./markers";

const DEFAULT_CENTER = { lat: 48.8566, lng: 2.3522 };
const DEFAULT_ZOOM = 7;

export const GoogleMaps = ({
locations,
className,
}: {
locations: ReadonlyArray<google.maps.LatLngLiteral>;
className?: string;
}) => {
...

useEffect(() => {
// Display the map
if (ref.current) {
const map = new window.google.maps.Map(ref.current, {
center: DEFAULT_CENTER,
zoom: DEFAULT_ZOOM,
});

// Displays single markers on map when called
addSingleMarkers({ locations, map });
}
}, [ref, locations]);

...
};

Of course, let’s not forget to update the MapComponent to provide the locations.

// I took the example of adding two markers for these two locations
export const LOCATIONS = [
{ lat: 48.8566, lng: 2.3522 },
{ lat: 47.1533, lng: 2.9123 },
];

export const MapComponent = () => (
<GoogleMapsWrapper>
<GoogleMaps locations={LOCATIONS} />
</GoogleMapsWrapper>
);

We are now able to see on the map the two markers that correspond to the locations passed to the component !

Add marker clusters

Let’s now add the marker clusters behavior. We want to specify a range in which all markers would be grouped into a single marker cluster.

First, we need to add another library to handle clusters: @googlemaps/markerclusterer

yarn add @googlemaps/markerclusterer

Just like we did for single markers, we can build a method addClusterMarkers that will be used to compute marker clusters and display them on the map. We need to use the method addSingleMarkers that we created just before.

import {
MarkerClusterer,
SuperClusterAlgorithm,
} from '@googlemaps/markerclusterer';

import { addSingleMarkers } from './addSingleMarkers';

export const addClusterMarkers = ({
locations,
map,
}: {
locations: ReadonlyArray<google.maps.LatLngLiteral>;
map: google.maps.Map | null | undefined;
}) => {
const markers = addSingleMarkers({locations, map});

// Merge markers into clusters
new MarkerClusterer({
markers,
map,
algorithm: new SuperClusterAlgorithm({
radius: 350, // cluster size
}),
});
};

Nb: the radius attribute of SuperClusterAlgorithm defines the radius of the cluster. Increasing its value will group more markers under the same cluster (and hence create less clusters). Decreasing does the opposite.

Same as we did earlier, the next step is to pass our clusters to the map, to load them during when rendering the map. Here, we can simply update the useEffect in GoogleMaps component to load clusters instead of single markers.

// GoogleMaps.tsx

useEffect(() => {
// Display the map
if (ref.current) {
const map = new window.google.maps.Map(ref.current, {
center: DEFAULT_CENTER,
zoom: DEFAULT_ZOOM,
});

// Displays cluster markers on map when called
addClusterMarkers({ locations, map });
}
}, [ref, locations]);

And that’s basically it, markers are now grouped under clusters when they are within the radius defined above !

In case you need it, here is a full Github repository that does the whole implementation and allow you to run all of the above locally: https://github.com/scottpicquerey/react-google-maps-api

Thank you very much for reading this article 🙏

For more information you can check the Github pages of the packages installed above and Google Maps Platform’s documentation.

Special thanks to Vincent Francois for helping me on the article 🎉

--

--