Reputation: 81
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
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
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
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
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