smeijer / leaflet-geosearch

A geocoding/address-lookup library supporting various api providers.
https://smeijer.github.io/leaflet-geosearch/
MIT License
1.02k stars 270 forks source link

Adding a function to get the Location of the selected result #329

Open SalahAdDin opened 2 years ago

SalahAdDin commented 2 years ago

Thanks for this greap library, we could replace react-leaflet-search with this library.

Something is missing: we want to get the location from the selected result.

Right now we do it by a fired event(geosearch/showlocation) as follows:

const LeafLetGeoSearch = ({
  onLocationResult,
}: {
  onLocationResult: (latLng: GeometryT) => void;
}) => {
  const provider = new OpenStreetMapProvider();

  const controlOptions = {
    provider,
    style: 'bar',
    autoClose: true,
    keepResult: true,
    zoomLevel: 7,
  };

  const searchControl: Control = GeoSearchControl(controlOptions);

  const map = useMap();

  // TODO: Handle it to be settled up once
  map.on('geosearch/showlocation', (result) => {
    if (result) {
      const {
        location: { x, y },
      } = result as LeafletEvent & { location: SearchResult };

      onLocationResult({ lat: x, lng: y });
    }
  });

  useEffect(() => {
    map.addControl(searchControl);

    return () => {
      map.removeControl(searchControl);
    };
  }, []);

  return null;
};

The problem with this approaching is the event is fired many times, and it can affect the render performance:

Screen Shot 2022-06-18 at 00 46 19

The aforementioned library uses a callback(onChange) to handle it.

What's about using a kind of function to get it?

Thank you

cyango commented 1 year ago

The function fires many times because you should use map.on inside useEffect, as it behaves like addEventlistener.

So something like:



  const onShowLocation = (result: LeafletEvent) => {
    if (result) {
   // read location here
    }
  };

  useEffect(() => {
    map.addControl(searchControl);

    map.on('geosearch/showlocation', onShowLocation);

    return () => {
      map.removeControl(searchControl);

      map.off('geosearch/showlocation', onShowLocation);
    };
  }, []);

...```