1

I am using React Leaflet and react-leaflet-markercluster. I have a lot of markers and if parent's state is changed, marker cluster rerendering takes longer time. For this reason, cluster components are memoized.

When I click on a polygon, I want to delete it's marker from map and markercluster. I am looking for a way to do it without rerendering markercluster. I tried this code, but it doesn't work:

React.useEffect(() => {
    Object.keys(mapRef?._layers).forEach(function (key) {
      const leafletLayer = mapRef?._layers[key];

      if (typeof leafletLayer?.getAllChildMarkers === "function") {
        const allMarkers = leafletLayer.getAllChildMarkers();
        allMarkers.forEach((marker) => {
          const dataId = marker.options.id;
          const foundMarker = props.selected.find(
            (selectedAsset) => selectedAsset === dataId
          );
          if (foundMarker) {
            console.log("remove marker from map", marker);
            mapRef.removeLayer(marker);
          }
        });
      }
    });
  }, [mapRef, props.selected]);

codesandbox

6
  • I spent some time with this, tough question. I think the secret lies in being able to get a ref to the underlying leaflet element for the markercluster (easy), and then get an array of all the markers in that cluster layer. I can't seem to figure out how to do that though. If you know how to take an L.MarkerCluster and get an array of all the markers, I think we can do this, by removing the markers directly from the leaflet element and leaving react out of it. It seems getAllChildMarkers is only available from within an event callback? Commented Mar 9, 2021 at 16:30
  • @SethLutske thanks for taking a look at this. After all, I just removed react-leaflet-markercluster wrapper and now I am using only Leaflet.markercluster. I am storing markercluster reference in a variable which is out of react component. I am able to delete markers in React.memo function of MapElements component where I can access markercluster reference and delete markers.
    – Matt
    Commented Mar 9, 2021 at 16:57
  • I'm glad that works for you. I'm sure there's a way to do in within the component, but with react-leaflet-v3, we end up digging into the underlying leaflet components anyway. Its a delicate balance Commented Mar 9, 2021 at 16:59
  • @SethLutske I am working on a project where I need to integrate Leaflet with leaflet-geoman in a React project with thousands of geojsons and markers, which should be draggable and editable. It's super tricky to make all these things working together.
    – Matt
    Commented Mar 9, 2021 at 17:04
  • Sounds badass, post it here when its done! if possible. If you want the popups to be editable too, you can check out my react-leaflet-editable-popup, though I'm not sure how that would integrate with markercluster in the way you're using it. Good luck! Commented Mar 9, 2021 at 17:41

2 Answers 2

0

I decided to remove react-leaflet-markercluster wrapper and use only Leaflet.markercluster library, which I use like this:

const mcg = L.markerClusterGroup({
    chunkedLoading: true,
    showCoverageOnHover: false,
});

const MarkersCluster = ({ markers }) => {
    const { map } = useLeaflet();
    useEffect(() => {
        mcg.clearLayers();
        const markerList = markers.map(({ coords }) => {
            return L.marker(new L.LatLng(coords.latitude, coords.longitude), {
                icon: YOUR_ICON,
            });
        });

        mcg.addLayers(markerList);
        map.fitBounds(mcg.getBounds());
        map.addLayer(mcg);
    }, [markers, map]);


    return null;

};


export default MarkerCluster;

and use it:
<MarkerCluster marker={my_markers} />

Now, I can access cluster reference in React.memo of MapElements and remove markers and prevent rerendering whole cluster.

0

Instead of removing the marker from the rendered cluster, remove it from the source, i.e the GEOJSON data and then remove the clusterlayer and re-apply it.

Its a pretty unknown fact that render from new is a lot quicker than re-rendering.

Your old way is ok for small amounts of markers but not for 25K+

Not the answer you're looking for? Browse other questions tagged or ask your own question.