2

I've implemented autocomplete for my address field, but the json returned from the Google Maps Places Autocomplete doesn't include the geocoded coords for the places.

There are some answers out there that don't seem to fit. For instance, this one refers to things like google.maps.places.Autocomplete(input, options); which I don't think is a thing in React Native.

Other answers appear to be based on react-native-google-places-autocomplete, but I've implemented this myself and I'd love to not do it again using that module.

Here's my method where I call the API.

  async handleAddressChange() {
    const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleAPIKey}&input=${this.state.address}`;
    try {
      const result = await fetch(url);
      const json = await result.json();
      this.setState({ addressPredictions: json.predictions });
    } catch (err) {
      console.error(err);
    }
  }

  setAddress(prediction) { 
    this.setState({ address: prediction.description, showPredictions: false });
  }

The API response doesn't have any place or geometry property on it:

Object {
  "description": "1234 Some Avenue Northeast, Washington, DC, USA",
  "id": "4c79fba1b3a5ad33478b79b54896a75a4d56ca53",
  "matched_substrings": Array [
    Object {
      "length": 4,
      "offset": 0,
    },
  ],
  "place_id": "ChIJneQ1fBO5t4kRf8mTw4ieb4Q",
  "reference": "ChIJneQ1fBO5t4kRf8mTw4ieb4Q",
  "structured_formatting": Object {
    "main_text": "1234 Some Avenue Northeast",
    "main_text_matched_substrings": Array [
      Object {
        "length": 4,
        "offset": 0,
      },
    ],
    "secondary_text": "Washington, DC, USA",
  },
  "terms": Array [
    Object {
      "offset": 0,
      "value": "1600",
    },
    Object {
      "offset": 5,
      "value": "Maryland Avenue Northeast",
    },
    Object {
      "offset": 32,
      "value": "Washington",
    },
    Object {
      "offset": 44,
      "value": "DC",
    },
    Object {
      "offset": 48,
      "value": "USA",
    },
  ],
  "types": Array [
    "street_address",
    "geocode",
  ],
}

Jonathan Tuzman
  • 11,568
  • 18
  • 69
  • 129
  • There should be other properties in the response besides the predictions, which amount only for the suggestions prior to the user actually selecting one of them – ffflabs Apr 22 '19 at 23:37
  • 2
    With this data, make a [Place Details Request](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceDetailsRequest) to the Places API with the `place_id` returned, which is `ChIJneQ1fBO5t4kRf8mTw4ieb4Q` in your above example. – MrUpsidown Apr 23 '19 at 06:53
  • 1
    @MrUpsidown this does appear to be the best way. Happy to mark it **the** answer if you post it as an answer. – Jonathan Tuzman Apr 23 '19 at 14:48
  • Here you are! See below :) – MrUpsidown Apr 24 '19 at 07:19

2 Answers2

9

I have found a solution for the same-

Just use like this-

<GooglePlacesAutocomplete
        GooglePlacesDetailsQuery={{ fields: "geometry" }}
        fetchDetails={true} // you need this to fetch the details object onPress
        placeholder="Search"
        query={{
          key: "API_KEY_GOES_HERE",
          language: "en", // language of the results
        }}
        onPress={(data: any, details: any = null) => {
          console.log("data", data);
          console.log("details", details);
          console.log(JSON.stringify(details?.geometry?.location));
        }}
        onFail={(error) => console.error(error)} />
hamid saifi
  • 184
  • 2
  • 3
3

Once you have the place id (ChIJneQ1fBO5t4kRf8mTw4ieb4Q for the example in your question), you can do a place details request.

Make sure you include the Places library in your API call: https://maps.googleapis.com/maps/api/js?libraries=places and a valid API key.

function initialize() {

    var map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: new google.maps.LatLng(0, 0),
        zoom: 15
    });

    var service = new google.maps.places.PlacesService(map);

    service.getDetails({
        placeId: 'ChIJneQ1fBO5t4kRf8mTw4ieb4Q'
    }, function(place, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {

            // Create marker
            var marker = new google.maps.Marker({
                map: map,
                position: place.geometry.location
            });

            // Center map on place location
            map.setCenter(place.geometry.location);
        }
    });
}

initialize();
#map-canvas {
  height: 160px;
}
<div id="map-canvas"></div>

<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initialize">
</script>
MrUpsidown
  • 21,592
  • 15
  • 77
  • 131
  • "Places detail request" is the right way to go. However, this answer appears to be for a web application rather than React Native, and uses `google.maps` which I'm fairly sure RN doesn't have access too. Still, making a places detail request with a simple fetch works in my situation. – Jonathan Tuzman Apr 24 '19 at 13:49
  • Yes, this is for a JS app, but you get the idea. You can make the same request to the [web service](https://developers.google.com/places/web-service/details). – MrUpsidown Apr 24 '19 at 14:06
  • From a cost perspective wont this be making an extra API call? – Dhruv Sep 02 '23 at 21:27