Search code examples
reactjsleafletreact-leafletreact-leaflet-v3

React Leaflet v3 : Good way to create a control


I'm displaying a map with react leaflet v3 in my react app.

I just want to add a custom control, but I can't figure out what's the good way to do that.

Actually, i do it like that, but it seems to be not working.

function DptCtl(props) {
    // Control
    const map = useMap();

    // List of dpts and provinces
    const dpts = useSelector(dptsSelector);

    L.Control.Dpts = L.Control.extend({
        onAdd(map) {
            const container = L.DomUtil.create('div');
            const input = L.DomUtil.create('input', container);

            
            return container;
        },
        onRemove(map) {}
    })

    L.Control.dpts = function (opts) {
        return new L.Control.Dpts(opts);
    }

    useEffect(() => {
        const control = L.Control.dpts({ position: props.position })
        map.addControl(control)

        return () => {
            map.removeControl(control)
        }
    }, [dpts])

    return null;
}

Solution

  • React-Leaflet v3 provides the createControlComponent Hook in the Core API that takes in an instance of a Leaflet control and returns a Leaflet element.

    Here is an example using Leaflet's Zoom control:

    import L from 'leaflet';
    import { createControlComponent } from '@react-leaflet/core';
    
    const createControlLayer = (props) => {
      // Set up an instance of the control:
      const controlInstance = new L.Control.Zoom(props);
    
      return controlInstance;
    };
    
    // Pass the control instance to the React-Leaflet createControlComponent hook:
    const customControl = createControlComponent(createControlLayer);
    
    export default customControl;
    

    Then, add the new custom control layer to the Map:

    <MapContainer
      center={[37.0902, -95.7129]}
      zoom={3}
      zoomControl={false}
      style={{ height: '100vh', width: '100%', padding: 0 }}
      whenCreated={(map) => setMap(map)}
    >
      <CustomControl />
      <LayersControl position="topright">
        <LayersControl.BaseLayer checked name="Map">
          <TileLayer
            attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            url={maps.base}
          />
        </LayersControl.BaseLayer>
      </LayersControl>
    </MapContainer>
    

    DEMO