How to display Popups on a Mapbox Map in React
This is part 3 (and the last one) of a multi-part React tutorial on Mapbox.
In part 1, we simply focus on displaying a Mapbox map and adding a geocoder to look up addresses. We even managed to re-center our map to the selected address.
In part 2, we learned how to display markers on a Mapbox map.
Part 3 will be focusing on popups and removing markers from a map.
Let’s get started!
Want to become a Next.js pro?
I am putting together an online course on Next.js. If you are interested, sign up and I will keep you updated.
Step 1. Create and display a Popup component
Once again, we will be using the react-map-gl library which offers a nice Popup component. So I will go ahead and create a CustomPopup
component to display the address after clicking on a marker.
import ReactMapGL, {Marker, Popup } from 'react-map-gl';
const CustomPopup = ({index, marker, closePopup}) => {
return (
<Popup
latitude={marker.latitude}
longitude={marker.longitude}
onClose={closePopup}
closeButton={true}
closeOnClick={false}
offsetTop={-30}
>
<p>{marker.name}</p>
</Popup>
)};
Again, thanks to react-map-gl, we get a Popup component which takes lat/long, but also offsetTop
(meaning, in this case, I want the popup to appear on top of the marker).
To make it work, we add need an onClick on our markers called openPopup
. This function will set which marker was clicked thanks to its unique index.
const CustomMarker = ({index, marker, openPopup}) => {
return (
<Marker
longitude={marker.longitude}
latitude={marker.latitude}>
<div className="marker" onClick={() => openPopup(index)}>
<span><b>{index + 1}</b></span>
</div>
</Marker>
)};
And back to our parent component:
constructor(props) {
super(props);
this.state = {
...,
selectedIndex: null,
...
};
}
setSelectedMarker = (index) => {
this.setState({ selectedIndex: index })
}
closePopup = () => {
this.setSelectedMarker(null)
};
openPopup = (index) => {
this.setSelectedMarker(index)
}
render() {
return(
...
{
this.state.markers.map((marker, index) => {
return(
<CustomMarker
key={`marker-${index}`}
index={index}
marker={marker}
openPopup={this.openPopup}
/>
)
})
}
...
)
}
To recap what just happened, we:
- added a selectedIndex to our parent state and a
setSelectedMarker
function to set the selectedIndex - created a
openPopup
andclosePopup
to set the index to either the clicked marker or null. - passed openPopup to our
customMarker
component so that when clicked, we can later open the right popup
Now that we have set our index, let’s also display a popup when the index is not null. So after our markers, we add:
{
selectedIndex !== null &&
<CustomPopup
index={selectedIndex}
marker={markers[selectedIndex]}
closePopup={this.closePopup}
/>
}
We only pass the right marker (to display the correct content), but also our closePopup
function.
Step 2. Remove Markers in a Mapbox map
I promised at the beginning that I would show you how to remove markers, so here we go!
As a design decision, I have decided to add my Remove button in the popup. So when a user clicks on a marker, a popup appears with the address and a remove button. When clicked, the marker will disappear from the map.
First, let’s start by creating our remove
function. We will use the marker’s index to filter it out of our markers array. We will also be setting selectedIndex
to null as the marker will disappear with its popup. Then, we will be passing this function to our customPopup
.
remove = (index) => {
this.setState(prevState => ({
markers: prevState.markers.filter((marker, i) => index !== i),
selectedIndex: null
}))
}
...
render() {
return(
...
{
selectedIndex !== null &&
<CustomPopup
index={selectedIndex}
marker={markers[selectedIndex]}
closePopup={this.closePopup}
remove={this.remove}
/>
}
...
);
}
Finally, let’s add a remove button to our customPopup
and using our remove
function:
const CustomPopup = ({index, marker, closePopup, remove}) => {
return (
<Popup
latitude={marker.latitude}
longitude={marker.longitude}
onClose={closePopup}
closeButton={true}
closeOnClick={false}
offsetTop={-30}
>
<p>{marker.name}</p>
<div>
<Button color="secondary" onClick={() => remove(index)}>Remove</Button>
</div>
</Popup>
)};
A fairly straightforward way to easily remove markers on a map!
Resources
The following libraries are useful for this tutorial:
react-map-gl: https://www.npmjs.com/package/react-map-gl
react-mapbox-gl-geocoder: https://www.npmjs.com/package/react-mapbox-gl-geocoder
bootstrap: https://www.npmjs.com/package/bootstrap
reactstrap: https://www.npmjs.com/package/reactstrap
And here is the link to Mapbox and it's examples: https://docs.mapbox.com/help/tutorials/
That’s it! This is the final part our this tutorial on Mapbox and React. We have learned how to:
- display a map
- add a geocoder to look up addresses
- add and remove markers
- display popups for a specific marker
I hope this was helpful.
For more Mapbox tutorials in React: