starbvuks
starbvuks

Reputation: 101

Show popup for only one Marker react map gl

I'm using react-map-gl and states so that when a marker is clicked on the popupOpen is set to true and the popup shows up.

This works with maps with only one marker but when I use a map fuction to send coords of multiple markers, clicking on any of them opens all popups because the binded state cotrols them all.

How do I set it up so that only the popup related to a specific marker shows up?

// state
const [popupOpen, setPopupOpen] = useState(false);

// marker & popup

          {landmarkData.map((data, index) => (
            <div key={data._id}>
              <Marker
                key={index}
                longitude={data.longitude}
                latitude={data.latitude}
                onClick={() => setPopupOpen(true)}
              >
                <RoomIcon fontSize="small" style={{fill: "red"}} />
              </Marker>
              {popupOpen && (
                <Popup
                  key={index}
                  latitude={data.latitude}
                  longitude={data.longitude}
                  onClose={() => setPopupOpen(false)}
                  closeButton={true}
                  offsetLeft={10}
                >
                  <span style={{fontSize: "1vw", fontFamily: "Poppins"}}>
                    {data.name}
                  </span>
                </Popup>
              )}
            </div>
          ))}

Upvotes: 1

Views: 3255

Answers (2)

Aziz
Aziz

Reputation: 1

You need to track each popup state individually and then prevent the propagation of the onClick so it does not close.

// state
const [popupOpen, setPopupOpen] = useState({});

// marker & popup

          {landmarkData.map((data, index) => (
            <div key={data._id}>
              <Marker
                key={index}
                longitude={data.longitude}
                latitude={data.latitude}
                onClick={(e) => {
            // If we let the click event propagate to the map, it will immediately close the popup
            // with `closeOnClick: true`
            e.originalEvent.stopPropagation();
            setPopupOpen({ [data._id]: true });
          }}
              >
                <RoomIcon fontSize="small" style={{fill: "red"}} />
              </Marker>
              {popupOpen[data._id] && (
                <Popup
                  key={index}
                  latitude={data.latitude}
                  longitude={data.longitude}
                  onClose={() => setPopupOpen(false)}
                  closeButton={true}
                  offsetLeft={10}
                >
                  <span style={{fontSize: "1vw", fontFamily: "Poppins"}}>
                    {data.name}
                  </span>
                </Popup>
              )}
            </div>
          ))}

It is similar to @Manish answer (credit to him) but need to prevent the propagation and use setPopupOpen({ [data._id]: true }) if you want to only have one popup at a time.

Upvotes: 0

Manish
Manish

Reputation: 5213

You should individually track the popup open state; like this:


// state
const [popupOpen, setPopupOpen] = useState({});

// render


          {landmarkData.map((data, index) => (
            <div key={data._id}>
              <Marker
                key={index}
                longitude={data.longitude}
                latitude={data.latitude}
                onClick={() => setPopupOpen({...popupOpen, popupOpen[data._id]: true })}
              >
                <RoomIcon fontSize="small" style={{fill: "red"}} />
              </Marker>
              {popupOpen[data._id] && (
                <Popup
                  key={index}
                  latitude={data.latitude}
                  longitude={data.longitude}
                  onClose={() => setPopupOpen(false)}
                  closeButton={true}
                  offsetLeft={10}
                >
                  <span style={{fontSize: "1vw", fontFamily: "Poppins"}}>
                    {data.name}
                  </span>
                </Popup>
              )}
            </div>
          ))}

Upvotes: 2

Related Questions