I have a list, and through clicking on the list Elements, I want to open the pop up on the marker. Currently, the pop up only opens when the marker is clicked.
This is how I create the marker and the pop ups
import React from 'react';
import {
CircleMarker,
Popup,
} from 'react-leaflet';
class PointsLayer extends React.Component {
render() {
const { data } = this.props;
return (
data.map(point => {
return (
<CircleMarker
key={point.id}
center={point.coordinates}>
<Popup>
Fancy Pop Up
</Popup>
</CircleMarker>
)
})
)
}
and
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
Map,
} from 'react-leaflet';
import L from 'leaflet';
import PointsList from './PointsList;
import PointsLayer from './PointsLayer;
class Map extends React.Component {
componentDidMount() {
this.map = this.mapInstance.leafletElement;
}
render() {
const { data } = this.props;
return (
<>
<Map
ref={e => { this.mapInstance = e }}}>
<TileLayer
url=..." />
<PointsLayer
data={data} />
</Map>
<PointsList
data={data} />
</>
)
}
}
Each data point from data
is a marker on the <Map />
through the <PointsLayer />
component, and a listentry in <PointsList />
.
I want to open the pop up in <PointsLayer />
when the corrresponding entry in <PointsList />
is clicked.
How would I do that?
To open Popup Marker.openPopup()
method could be utilized. The following component demonstrates how to access native Marker object in react-leaflet
library and open Popup:
function MarkerExample(props) {
const markerRef = useRef(null);
const { center, content, openPopup } = props;
useEffect(() => {
markerRef.current.leafletElement.openPopup();
}, []);
return (
<CircleMarker ref={markerRef} center={center}>
<Popup>{content}</Popup>
</CircleMarker>
);
}
Here is a list of changes for your example:
a)introduce a separate component for a marker which accepts a openPopup
prop to determine whether Popup needs to be opened or not:
function PointMarker(props) {
const markerRef = useRef(null);
const { center, content, openPopup } = props;
useEffect(() => {
if (openPopup) markerRef.current.leafletElement.openPopup();
}, [openPopup]);
return (
<CircleMarker ref={markerRef} center={center}>
<Popup>{content}</Popup>
</CircleMarker>
);
}
b)modify PointsList
component to transfer the index of selected item via event handler, like this:
function PointsList(props) {
const { data, onItemClick } = props;
return (
<div>
<ul>
{data.map((item, index) => (
<li
key={index}
onClick={e => {
onItemClick(index);
}}
>
{item.name}
</li>
))}
</ul>
</div>
);
}
c)And finally in a map component introduce the index of selected marker as state variable. Now once external element is clicked, update selected index to get Popup opened:
function MapExample(props) {
const [selected, setSelected] = useState();
const { zoom, center, locations } = props;
function handleItemClick(index) {
setSelected(index);
}
return (
<div>
<PointsList data={locations} onItemClick={handleItemClick} />
<Map center={center} zoom={zoom}>
<TileLayer url="https://{s}.tile.osm.org/{z}/{x}/{y}.png" />
<PointsLayer selectedIndex={selected} data={locations} />
</Map>
</div>
);
}
Here is a demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With