Building an Interactive Map with Mapbox & React

Lauryn Kim
Geek Culture
Published in
5 min readApr 8, 2021

Mapbox API is a great tool to build custom, interactive maps. However, integrating Mapbox into a bigger application might feel tricky at first — personally, I found myself spending some time searching for resources outside of the documentation to incorporate key features into my React application. If you can relate, hopefully this article will be the last you’ll ever read! Here I will be breaking down the steps to build an interactive map using two libraries, react-map-gl and react-map-gl-geocoder. Specifically, I’ll go over how to: 1) render a map, 2) incorporate geocoder, 3) create markers, and 4) add popups.

1. Create a React app and install dependencies

To begin, let’s set up a project using Create React app and install react-map-gl and react-map-gl-geocoder. Paste the following into your terminal:

npx create-react-app mapbox-project
cd mapbox-project
npm i react-map-gl react-map-gl-geocoder
npm start

2. Get a Mapbox API token

Next, we must create an account for Mapbox. If you aren’t automatically redirected to your dashboard with a token, create one by clicking on the blue “Create a token” button.

3. Create a map

Now that we have an API token, let’s begin coding! Moving forward, I will be using class components.(If you’d prefer to use stateless components instead, check out the documentation.) To build a map, we will take advantage of the ReactMapGl component provided by react-map-gl. It takes in a number of props, including an API token, viewport, mapStyle, and onViewportChange.

  • viewport: Dimensions of your map, the center point, and the zoom constant.
  • mapStyle: Various styles are available on Mapbox (with different combinations of color scheme, street-view, labels, etc.), or even create your own here.
  • onViewportChange: Function that controls viewport transition (i.e. updating the viewport when a user drags the map).

After saving, you should be able to see a map rendering on your localhost!

Rendered map

4. Add a geocoder

Next, let’s add a geocoder onto the map using react-map-gl-geocoder. The library conveniently provides us the Geocoder component that takes in several props, including an API token, mapRef, onResult, and onViewportChange, position, and countries. Import the styling and add the Geocoder component inside ReactMapGl.

The following descriptions are derived from the documentation:

  • mapRef: Ref for react-map-gl map component.

To add this prop, define a variable (like the example below). Then, add a ref key on the ReactMapGl component.

mapRef = React.createRef()
  • onViewportChange: Is passed updated viewport values after executing a query
  • position: Position on the map to which the geocoder control will be added. Valid values are "top-left", "top-right", "bottom-left", and "bottom-right".
  • countries: A comma separated list of country codes to limit results to specified country or countries.

Check out the documentation for additional customization props!

After passing in props to the Geocoder component and saving the file, you should be able to see a search bar on your map. You can type in a location and re-center the map on the location’s coordinates upon selection!

Geocoder search bar

4. Create and render markers on your map

Now let’s move onto markers. Import the Marker component from react-map-gl. The only required props for Marker are latitude and longitude. To add a marker, simply insert the component with latitude and longitude inside the parent component like so:

import ReactMapGl, {Marker} from 'react-map-gl'
...
<ReactMapGl
...
/>
<Marker
latitude={insert latitude}
longitude={insert longitude}
>
[insert image or custom marker]
</Marker>
</ReactMapGl>
...

Rendering a marker with hardcoded values is cool, but we want to make an interactive map. By storing location information in our local state, we will be able to create markers upon searching and selecting addresses.

this.state = {
...
currMarker: null,
markers: []
}

The Geocoder component accepts an onResult prop, where we can pass in a function to be executed when the geocoder input is selected. We will create a handleResult function that updates the values of currentMarker and pass it onto onResult (remember to bind it inside of the constructor!).

handleResult(result) {
this.setState({
currMarker: {
name: result.result.place_name,
latitude: result.result.center[1],
longitude: result.result.center[0]
}
})
}

Next, we will create a function to pass into a button’s onClick event attribute to save the currentMarker on our map! This function will update the state by pushing currentMarker to the maps array.

addMarker() {
const {currMarker} = this.state
this.setState(prevState => ({
markers: [...prevState.markers, currMarker],
currMarker: null
}))
}

To finally render markers for the locations saved in our maps array, simply map through (no pun intended!) the array inside of the map component, passing in the respective props for each. Your code should look like the example below:

With the above code, you should be able to add markers on your map by selecting a location and clicking on the add button!

Map with markers

4. Create pop-ups

Last but not least, we will create pop-ups for the markers on our map. Again, we will be using the built-in Popup component provided by react-map-gl. It accepts numerous props — for our purposes, we’ll include the following: mapRef, latitude, longitude, closeButton, closeOnClick, and onClose.

  • closeButton: (default: true) If true, a close button will appear in the top right corner of the popup.
  • closeOnClick: (default: true) If true, the popup will close when the map is clicked.
  • onClose: Callback when the user closes the popup.

To render a pop-up when you click on a marker, let’s add selectedMarker to our local state and add two instance methods, handleMarkerClick and handleClose. The handleMarkerClick method will be invoked when a marker is clicked and will update selectedMarker to hold that marker’s information. The handleClose method will be invoked when the close button on the pop-up is clicked and will update handleMarkerClick to null.

Here is the final code:

Once you save your code, you should be able to click on a marker on your map to see a pop-up!

Pop-up

Congrats, you now have an interactive map under your belt! 🎉 This is just the beginning — try implementing more features to add more layers of complexity to your map. Thanks for reading, and feel free to reach out with any questions, comments, or concerns!

References

https://github.com/facebook/create-react-app

https://docs.mapbox.com/mapbox-gl-js/api/

https://visgl.github.io/react-map-gl/docs/get-started/get-started

https://www.npmjs.com/package/react-map-gl-geocoder

--

--