MsUdems
MsUdems

Reputation: 81

Mapbox Popup only opens once and never again

I am creating a React Mapbox App, and I have an issue with popups. When I render the map, all the Markers show correctly on the map. Then I click on the Marker and a Popup on that marker opens, with correct data and everything.

However, once I close that Popup I can't open a new Popup. Not even the same Popup. I tried to console.log() the data I get on click, and it is correct (object of pin data: lat, long, id ...)

Here is my code:

import { useState, useEffect } from "react";
import Map, { Marker, Popup } from "react-map-gl";
import axios from "axios";
import "mapbox-gl/dist/mapbox-gl.css";
import "./App.css";
import { Room } from "@material-ui/icons";
import { format } from "timeago.js";

function App() {
  const [pins, setPins] = useState([]);
  //Contains selected pin
  const [selectedPin, setSelectedPin] = useState(null);
  const [showPopup, setShowPopup] = useState(false);

  //Get all pins from the database
  useEffect(() => {
    const getPins = async () => {
      try {
        const response = await axios.get("/pins");
        setPins(response.data);
      } catch (error) {
        console.log(error);
      }
    };
    getPins();
    //console.log(pins);
  }, []);

  useEffect(() => {
    const listener = (e) => {
      if (e.key === "Escape") {
        setSelectedPin(null);
      }
    };
    window.addEventListener("keydown", listener);

    return () => {
      window.removeEventListener("keydown", listener);
    };
  }, []);

  const handlePinClick = (pin) => {
    console.log("here");
    setSelectedPin(pin);
    console.log(pin);
  };

  return (
    <div className="App">
      <Map
        initialViewState={{
          longitude: 31.1656,
          latitude: 48.3794,
          zoom: 5,
        }}
        style={{ width: "100vw", height: "100vh" }}
        mapStyle="mapbox://styles/msude/cl0b56qxj000215qj1qgx7faq"
        mapboxAccessToken={process.env.REACT_APP_MAPBOX}
      >
        {pins.map((pin) => (
          <>
            <Marker longitude={pin.long} latitude={pin.lat} anchor="bottom">
              <Room
                style={{ color: "red", cursor: "pointer" }}
                onClick={() => {
                  handlePinClick(pin);
                }}
              />
            </Marker>
            {selectedPin && (
              <Popup
                key={selectedPin._id}
                longitude={selectedPin.long}
                latitude={selectedPin.lat}
                anchor="bottom"
                onClose={() => setSelectedPin(null)}
              >
                <div className="popup">
                  <label>Title</label>
                  <h2>{selectedPin.title}</h2>
                  <label>Description</label>
                  <h2>{selectedPin.description}</h2>
                  <label>Type of forces</label>
                  <label>Est. number of forces</label>
                  <h2>{selectedPin.number}</h2>
                  <label>Added on</label>
                  <h2>{format(selectedPin.createdAt)}</h2>
                </div>
              </Popup>
            )}
          </>
        ))}
      </Map>
    </div>
  );
}

export default App;

I must be missing something, but I have been struggling with this issue for the past two days and can't seem to find the solution.

Upvotes: 8

Views: 3239

Answers (4)

Nick Prozee
Nick Prozee

Reputation: 2913

I had the same issue and fixed this more simply.

React uses key prop in order to determine if a component should be mounted. When the key changes, a new component gets mounted. My guess is that the _id you are providing is null or equal to previous value.

Lets try to use this trick for the popup :) - use the lat and lng values to generate the key

<Popup key={popup.lat + popup.lng} latitude={popup.lat} longitude={popup.lng}>
  {popup.children}
</Popup>

Upvotes: 4

merxi beaucoup
merxi beaucoup

Reputation: 1

I had that issue before , try

  onClick={e => {       
        e.originalEvent.stopPropagation();
        setShowPopup(pin._id)}}

then set ,

onClose={() => setShowPopup(false)}>

also set

Upvotes: 0

nbst
nbst

Reputation: 225

apparently, you have to set closeOnClick={false} in your Popup component, closeOnClick is set to true by default, closeOnClick is used to close the popup when you click somewhere in the map, however, for some reason using closeOnClick seems to not destroy the popup but only 'hide it', then you're not able to show it again, i don't have found any workaround by keeping closeOnClick to true

Upvotes: 18

ahmetkilinc
ahmetkilinc

Reputation: 684

mapbox markers have "getPopup().isOpen()" to control if the markers popup is open and "togglePopup()" to toggle the markers popup functions. maybe you can use them for your problem.

for example when you click on your marker you fire a click event:

onMarkerClick = (marker) => {
    marker.togglePopup();
}

Upvotes: 0

Related Questions