SamSamskies / react-map-gl-geocoder

React wrapper for mapbox-gl-geocoder for use with react-map-gl
MIT License
123 stars 29 forks source link

Input field loses focus after selecting a result when "proximity" option is set #65

Closed humbkr closed 4 years ago

humbkr commented 4 years ago

Input field loses focus after selecting a result when "proximity" option is set.

To reproduce:

=> the map is updated, the search field still has focus, OK

=> the map is updated but the field loses the focus, KO

I also tested directly mapbox-gl-geocoder and I cannot reproduce the same behavior so the issue must be in react-map-gl-geocoder.

SamSamskies commented 4 years ago

Hi @humbkr, thanks for reporting the issue. I was able to reproduce the issue following your steps. I'm not sure why it's doing that, but it's possible that I could focus the input after every search to make sure that it always retains focus.

SamSamskies commented 4 years ago

I figured out why it's doing this. react-map-gl-geocoder is creating a new geocoder instance every time the props change. There was a use case for this in the past, but at the moment I cannot recall what it was. I think someone wanted to show and hide or move the geocoder based on some user controls they made. One of these days I'll get around to working on v3 and improving it so that users don't have to know about these details. For now, you can get it to work by memoizing props that are objects or functions. I've provided an example here https://codesandbox.io/s/react-map-gl-geocoder-memoize-object-and-function-props-dmwpb.

humbkr commented 4 years ago

Thanks for your help. I managed to make it work for my specific use case, albeit not how I would ideally like to.

The problem is that I would like to use proximity to filter subsequent searches, example:

In this case as the proximity parameter must be set in the onResult callback, there is no way of keeping the focus

More generally, there is no way of programmatically giving the focus to the input field, which would be super useful for example after the user has clicked on a "locate me" button.

SamSamskies commented 4 years ago

You can still accomplish what you are trying to do.

For the proximity, you can store the lat and lng in variables in state, update the proximity object values using those values, and then pass those as deps to the useMemo function in my example.

For setting focus to the input you can store a handle to the Mapbox geocoder object by using the onInit prop and imperatively focusing the input when a new Mapbox geocoder object is initialized which would happen after updating the proximity object reference. https://stackoverflow.com/questions/54576282/can-i-auto-focus-a-mapbox-gl-react-geocoder. Not the ideal solution, but I think that would work.

Another way you could go is to copy pasta the source code for react-map-gl-geocoder into your project and customize it to your needs. It's not much code https://github.com/SamSamskies/react-map-gl-geocoder/blob/master/src/index.js. I purposely put everything in one file to make it easy to copy pasta. This may be a better way to go, since I don't have much bandwidth to work on this these days, and have no idea when I'll get around to improving it.