Search code examples
javascriptreactjsleafletreact-leafletreact-leaflet-v3

Leaflet React get map instance in functional component


I want to have a button outside the map that changes the view to another coordinates.

Is there any way to get mapContainer instance to call their functions? Or how can I implement that function?

I tried to get it by using ref, but it's not working. Here is my current code

const zoom = 13;

function Map({ regionCoord, regionName }) {

    const mapRef = useRef();

    function handleFlyToClick() {
      // This don't work
      // const map = mapRef.current.leafletElement 
      // map.flyTo(regionCoord, zoom)
    }

 return (   
        <React.Fragment>
            <Grid container >
                <Grid item xs={10}>
                    {regionCoord && <MapContainer
                        ref={mapRef}                     
                        center={[50,50]} 
                        zoom={zoom}                    
                        >
                        <TileLayer
                            attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                        />            
   
                        <Marker position={regionCoord}>
                          <Popup>{regionName}</Popup>
                        </Marker>        
                    </MapContainer>}                               
                </Grid>
                <Grid item xs={2}>
                    <button onClick={handleFlyToClick}>Fly To</button>
                </Grid>
            </Grid>
        </React.Fragment>  
    )
    
}

export default Map

I'm using react-leaflet v3


Solution

  • You need to use a component which will include your button inside. To take the map instance use whenCreated prop of MapContainer. I think mapRef is not valid anymore with the latest version.

    MapContainer:

     const [map, setMap] = useState(null);
    
     <MapContainer
          center={[50, 50]}
          zoom={zoom}
          style={{ height: "90vh" }}
          whenCreated={setMap}
      >
    ...
    
    </MapContainer>
    <FlyToButton />  // use the button here outside of the MapContainer
    
    ....
    

    Create the component with the button and its event

    function FlyToButton() {
      const onClick = () => map.flyTo(regionCoord, zoom);
        
      return <button onClick={onClick}>Add marker on click</button>;
    }
    

    Demo