3

Hello I would like to load the map with the geolocation coordinates. Right now I have my map loaded on a defined center and when the event onClick happens, the view is set to the geolocate location. I just would like that this happens when I load the map the first time. My code below:

...
const Maps = () => {
// visitor geoLocalisation on the Map
  function LocationMarker() {
    const [position, setPosition] = useState(null);

    const map = useMapEvents({
      click() {
        map.locate();
      },
      locationfound(e) {
        setPosition(e.latlng);
        map.flyTo(e.latlng, map.getZoom());
      },
    });

    return position === null ? null : (
      <Marker
        position={position}
        icon={visitorIcon}
      >
        <Popup>You are here</Popup>
      </Marker>
    );
  }

  return (

    <MapContainer
      center={[48.856614, 2.3522219]}
      zoom={13}
      scrollWheelZoom
    >
      <TileLayer
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />

      <LocationMarker />

   </MapContainer>

  );
}
kboul
  • 13,836
  • 5
  • 42
  • 53
emarubi
  • 59
  • 5

2 Answers2

3

Replace useMapEvents with a useEffect which will be triggered on component mount. Use a map.locate().on("locationfound") event to trigger geolocation.

function LocationMarker() {
    const [position, setPosition] = useState(null);

    const map = useMap();

    useEffect(() => {
      map.locate().on("locationfound", function (e) {
        setPosition(e.latlng);
        map.flyTo(e.latlng, map.getZoom());
      });
    }, []);

    return position === null ? null : (
      <Marker position={position} icon={visitorIcon}>
        <Popup>You are here</Popup>
      </Marker>
    );
  }

Demo

kboul
  • 13,836
  • 5
  • 42
  • 53
  • Thanks so much kboul, your are a react god! :) – emarubi Feb 01 '21 at 11:14
  • Thanks :) Please accept the answer since it helped you. Please read [this](https://stackoverflow.com/help/accepted-answer) and [this](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – kboul Feb 01 '21 at 11:19
  • Hi Kboul, the code works very well, except for this Warning in the console: ```Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. at LocationMarker ``` I had a look at react useEffect documentation, but I dont understand how to create a Cleanup fonction to unsuscribe from my locate function. Can you please help me? – emarubi Feb 02 '21 at 09:03
  • There is no such warning on the demo I provided. it may come from another part of your app – kboul Feb 02 '21 at 09:22
  • But in the Warning is indicated at LocationMarker, so I suppose it comes from the hook. I put in teh useEffect this function that stops watching location previously initiated by map.locate ``` return function cleanup() { map.stopLocate(); }; ``` but I have the same Warning – emarubi Feb 02 '21 at 14:38
  • I cannot reproduce the issue since your app might be more complex. In the demo there is no such an error. You should not put map in the dependency array as it changes many times and that might cause the issue. You only want geolocation to execute **once** when the component mounts. Anyways this is a different issue regarding your original question. Again **please accept the answer since it solved your initial question** – kboul Feb 02 '21 at 14:48
  • Hi, in your Sandbox Code there is ans Esint warning ``` React Hook useEffect has a missing dependency: 'map'. Either include it or remove the dependency array.``` If you take the brakets away at line 19th, you have the same Warning that I described in my previous comment. Anyway as I want the geolocation to execute once when the component mounts I have to keep the dependency array, as you said. Thanks for your help. – emarubi Feb 02 '21 at 14:59
1

So finally I put map in the dependency and add a clenaup fonction to avoid Eslint and react Warnings above.

 function LocationMarker() {
    const [position, setPosition] = useState(null);

    const map = useMap();

    useEffect(() => {
      map.locate().on("locationfound", function (e) {
        setPosition(e.latlng);
        map.flyTo(e.latlng, map.getZoom());
      });
      return function cleanup() {
        map.stopLocate();
      };
    }, [map]);

    return position === null ? null : (
      <Marker position={position} icon={visitorIcon}>
        <Popup>You are here</Popup>
      </Marker>
    );
  }
emarubi
  • 59
  • 5