Search code examples
javascriptreactjsleafletreact-leafletreact-leaflet-v3

React Leaflet LayersControl.Overlay with multiple markers


I have a map that displays a marker for every diferent public facilities in a city and I want to have a group of checkboxes to filter this facilities according to its typology, one checkbox for typology. Each typology will have multiple markers and the map will only show the checked ones.
I'm using react-leaflet v3.

This is what I tried to do:

<MapContainer center={[50,50]} zoom={13} scrollWheelZoom={true} whenCreated={setMap}>
            <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />     
            <LayersControl position='topright'>
                {typologies.map((typology, index) => (                    
                    <LayersControl.Overlay key={index} checked name={typology}>
                        {publicFacilities.filter((publicFacility) => publicFacility.typology == typology ).map((publicFacility) => (                            
                            <Marker key={publicFacility._id} position={publicFacility.coordinates} />
                        ))}  
                    </LayersControl.Overlay>
                ))}
            </LayersControl>                    
        </MapContainer> 

typologies is a list of strings and publicFacilities is a list of objects.

But with this method I get a checkbox for every single facility.


Solution

  • You can use lodash groupBy to build your groups by typology.

    Then use Layer Groups to have several Markers behave as an Overlay.

    Something in the lines of:

    const groupedByTypology = groupBy(publicFacilities, "typology");
    
    return <LayersControl>
      {Object.keys(groupedByTypology).map(typology => (
        <LayersControl.Overlay key={typology} name={typology}>
          <LayerGroup>
            {groupedByTypology[typology].map(publicFacility => (
              <Marker key={publicFacility._id} position={publicFacility.coordinates} />
            ))}
          </LayerGroup>
        </LayersControl.Overlay>
      ))}
    </LayersControl>