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.

    We won't send you spam. Unsubscribe at any time.

    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:

    1. added a selectedIndex to our parent state and a setSelectedMarker function to set the selectedIndex
    2. created a openPopup and closePopup to set the index to either the clicked marker or null.
    3. 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:

    How to display a Mapbox Map and Geocoder in React
    This tutorial will be covering how to use Mapbox to display a map and a geocoder in React with the react-map-gl and react-mapbox-gl-geocoder libraries.
    How to display Markers on a Mapbox Map in React
    This tutorial will be covering how to create markers on a Mapbox map for a React app. We will be using the react-map-gl library.