Search code examples
javascriptleafletreact-leaflet

Set Marker on map using leaflet


I want click on my map and set a Marker with a circle around. It shows the map but I cannot set a marker.

console.log is not showing anything. It seems my handleMapClick function does not work.

import React, { useState } from "react";
import { MapContainer, TileLayer, Marker, Circle } from "react-leaflet";
import "leaflet/dist/leaflet.css";

const DynamicMap = () => {
  const [markerPosition, setMarkerPosition] = useState(null);
  const [circleCenter, setCircleCenter] = useState(null);
  const [circleRadius, setCircleRadius] = useState(10000); // Default radius in meters

  const handleMapClick = (e) => {
    const { lat, lng } = e.latlng;
    console.log("Clicked at:", lat, lng);
    setMarkerPosition([lat, lng]);
    setCircleCenter([lat, lng]);
  };

  return (
    <div>
      <MapContainer
        center={[51.505, -0.09]}
        zoom={10}
        style={{ width: "100%", height: "500px" }}
        onClick={handleMapClick}
      >
        <TileLayer
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        />
        {markerPosition && <Marker position={markerPosition} />}
        {circleCenter && <Circle center={circleCenter} radius={circleRadius} />}
      </MapContainer>
      <div>
        <input
          type="range"
          min="10000"
          max="200000"
          step="1000"
          value={circleRadius}
          onChange={(e) => setCircleRadius(e.target.value)}
        />
        <p>Circle Radius: {circleRadius} meters</p>
      </div>
      <div id="map"></div>
    </div>
  );
};

export default DynamicMap;

Solution

  • Unfortunately, React Leaflet does not support setting directly onClick prop on the <MapContainer> component.

    Instead, you should make a custom "map content component" as a child of <MapContainer>, which can use useMapEvent hook:

    function MapContent() {
      const [markerPosition, setMarkerPosition] = useState(null);
      
      const map = useMapEvent("click", (e) => {
        const { lat, lng } = e.latlng;
        console.log("Clicked at:", lat, lng);
        setMarkerPosition([lat, lng]);
      });
    
      return (
        <>
          {markerPosition && <Marker position={markerPosition} />}
        </>
      );
    }
    
    function DynamicMap() {
      return (
        <MapContainer>
          <MapContent />
        </MapContainer>
      );
    }