React-Leaflet Search Box Implementation
Asked Answered
B

4

7

Are there any resources showing a search box implementation with react-leaflet?

I'd like to have my map pins populate upon a search result that would query and retrieve my existing data.

ie:

const names = [

  {name: 'Joe', location: '40.734621, -73.989341 '},
  {name: 'Seth', location: '45.77621, -73.789654 '},

]

Then, after searching for Joe or Seth, the map would populate with the location coordinates.

I found examples for leaflet.js but couldn't find any examples spun with react-leaflet.

Blowy answered 16/1, 2018 at 22:3 Comment(0)
T
7

Take a look at leaflet-geosearch

Install it with npm install --save leaflet-geosearch

Then you just need to build a component with it:

import { GeoSearchControl, OpenStreetMapProvider } from 'leaflet-geosearch';

class Search extends MapControl {

  createLeafletElement() {
    return GeoSearchControl({
      provider: new OpenStreetMapProvider(),
      style: 'bar',
      showMarker: true,
      showPopup: false,
      autoClose: true,
      retainZoomLevel: false,
      animateZoom: true,
      keepResult: false,
      searchLabel: 'search'
    });
  }
}

export default Search;

And use your component in your Map:

render() {
  return (
    <Map>
      (...)
      <Search />
    </Map>
  );
}
Tilsit answered 5/2, 2018 at 12:28 Comment(3)
Thank you so much. I'll start implementing thisBlowy
Thanks, but how to append the search result in this Map?Pachysandra
@Pachysandra These are the docs: smeijer.github.io/leaflet-geosearch you can read the providers section to learn about how to implement search providers.Hydrolysis
C
7

I think I found a much easier way of doing this without needing to create and extend a class.

import { Map, useLeaflet } from 'react-leaflet'
import { OpenStreetMapProvider, GeoSearchControl } from 'leaflet-geosearch'

// make new leaflet element
const Search = (props) => {
    const { map } = useLeaflet() // access to leaflet map
    const { provider } = props

    useEffect(() => {
        const searchControl = new GeoSearchControl({
            provider,
        })

        map.addControl(searchControl) // this is how you add a control in vanilla leaflet
        return () => map.removeControl(searchControl)
    }, [props])

    return null // don't want anything to show up from this comp
}


export default function Map() {
  return (
    <Map {...otherProps}>
      {...otherChildren}
      <Search provider={new OpenStreetMapProvider()} />
    </Map>

  )
}
Columbian answered 22/7, 2020 at 20:58 Comment(4)
This is great, very helpful to me. One point to add is that if using the new v3 of react-leaflet, you will need to import useMap and not useLeaflet (deprecated).Almagest
@EricFurspan would you be kind enough to share your code? I am not able to make this work with react-leaflet v3. I also substituted <Map /> with <MapContainer />. It gives me error map is undefined, referring to the line where the mapControl is being addedOrrery
@Orrery I'd be glad to help. I only ask that you to put your question into its own post and send me its link and I will provide an answer to it with code. This post was already answered so let's not pollute it.Almagest
@EricFurspan Hi, I figured it out in the end! Thanks for your willingness to help though!Orrery
F
4
import { Map} from 'react-leaflet'
import { OpenStreetMapProvider, GeoSearchControl } from 'leaflet-geosearch'

// make new leaflet element
const Search = (props) => {
    const map = useMap() // access to leaflet map
    const { provider } = props

    useEffect(() => {
        const searchControl = new GeoSearchControl({
            provider,
        })

        map.addControl(searchControl) // this is how you add a control in vanilla leaflet
        return () => map.removeControl(searchControl)
    }, [props])

    return null // don't want anything to show up from this comp
}


export default function Map() {
  return (
    <MapContainer {...otherProps}>
      {...otherChildren}
      <Search provider={new OpenStreetMapProvider()} />
    </MapContainer >

  )
}

This is if you are using MapContainer instead of map

Flattie answered 16/6, 2022 at 10:18 Comment(1)
I have tried this in react-leaflet 4, and got the following: Uncaught (in promise) TypeError: t.trim is not a function at g (resultList.ts:73:1) at NewClass.onSubmit (SearchControl.ts:391:1) at NewClass.selectResult (SearchControl.ts:338:1) at HTMLInputElement.<anonymous> (SearchControl.ts:231:1)Rebroadcast
S
1

Solution That Worked while Using MapContainer. Leaflet.GeoSearch

npm i leaflet-geosearch

The Use the following the code.

import { useEffect } from "react";
// Search Location
import { GeoSearchControl, OpenStreetMapProvider  } from "leaflet-geosearch";
import { useMap, MapContainer  } from "react-leaflet";

/**
 * Search Location 
 */

 const SearchLocation = (props) => {
  // Get access to leaflet map
  const { provider } = props;

  // Get search control
  const searchControl = new GeoSearchControl({
    provider: provider,
  });

  //   Access Leaflet Map
  const map = useMap(props);
  useEffect(() => {
    // Add searchControl to Leaflet map
    map.addControl(searchControl);
    return () => map.removeControl(searchControl);
  });

  return null; // Do not render any thing
}

// Call SearchLocation in MyMap

const MyMap = () => {
  // ...
  return (
    <MapContainer>
       <SearchLocation provider={new OpenStreetMapProvider()} />
      {/* ... */}
    </MapContainer>
  );
};
Swollen answered 22/1 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.