jpa317
jpa317

Reputation: 35

@react-google-maps/api Autocomplete component returning undefined onPlaceChanged

I am having difficulty using the Autocomplete component in @react-google-maps/api. Autocomplete itself works and will display options. Clicking an option populates the input box but I only return 'undefined' from the Places Api. I have avoided using something like PlacesAutocomplete because I prefer the built in result rendering from Google.

Edited: App.js file should be minimally functional with use of an appropriate API key.

import React, { useState, useRef} from 'react';
import { Autocomplete, useLoadScript } from '@react-google-maps/api';

const placesLibrary = ['places']


function App() {
  const [searchResult, setSearchResult] = useState('')

  const autocompleteRef = useRef();

  const { isLoaded } =  useLoadScript({
    googleMapsApiKey: 'GOOGLE_API_KEY',
    libraries: placesLibrary
});

  const onLoad = () => {
     const autocomplete = autocompleteRef.current
  }

  const onPlaceChanged = (place) => {
    setSearchResult(place)
    console.log(searchResult)
  }

  if(!isLoaded) {
    return <div>Loading...</div>
    };


  return (
    <div className="App">
    
    
        <div id="searchColumn">
            <h2>Tide Forecast Options</h2>
            <Autocomplete
            onPlaceChanged={(place) => onPlaceChanged(place)}
            onLoad = {onLoad}>

                <input
                type="text"
                placeholder="Search for Tide Information"
                style={{
                    boxSizing: `border-box`,
                    border: `1px solid transparent`,
                    width: `240px`,
                    height: `32px`,
                    padding: `0 12px`,
                    borderRadius: `3px`,
                    boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
                    fontSize: `14px`,
                    outline: `none`,
                    textOverflow: `ellipses`,
                }}
                />
            </Autocomplete>
        </div>
    </div>    
  )}

export default App;

Upvotes: 2

Views: 14740

Answers (2)

Sankalpa
Sankalpa

Reputation: 41

Anyone looking for Typescript solution

const [searchResult, setSearchResult] = useState<google.maps.places.Autocomplete>()

  function onLoad(autocomplete: google.maps.places.Autocomplete) {
    setSearchResult(autocomplete);
  }

  function locationSelected() {
    if(searchResult) {
      const place = searchResult.getPlace();
      console.log("Search : ",place);
    } 
  }

  <Autocomplete onLoad={onLoad} onPlaceChanged={locationSelected}>
    <input  type="text" placeholder="Search"></input>
  </Autocomplete>

Upvotes: 0

Yrll
Yrll

Reputation: 2576

I was able to reproduce your code and found some unnecessary stuff you have included like the useRef, autocompleteRef but you could just clarify things in the comment. And also I did not find the way you used the onPlaceChanged and onLoad events on the @react-google-maps/api Library Docs. So I just based what I did there and removed some stuff you put.

Here's what the code looks like:

first is that onLoad() function for the <Autocomplete /> already had a built in parameter called autocomplete that returns the result of the autocomplete by using getPlace(). ref here. So what I did here is I changed the value of searchResult state with what the result of the autocomplete returns using setSearchResult(autocomplete) inside the onload() function.

  function onLoad(autocomplete) {
    setSearchResult(autocomplete);
  }

Then on the onPlaceChanged() function, I used the new searchResult value to get the place details.

  function onPlaceChanged() {
    if (searchResult != null) {
      //variable to store the result
      const place = searchResult.getPlace();
      //variable to store the name from place details result 
      const name = place.name;
      //variable to store the status from place details result
      const status = place.business_status;
      //variable to store the formatted address from place details result
      const formattedAddress = place.formatted_address;
      // console.log(place);
      //console log all results
      console.log(`Name: ${name}`);
      console.log(`Business Status: ${status}`);
      console.log(`Formatted Address: ${formattedAddress}`);
    } else {
      alert("Please enter text");
    }
  }

You can remove the comment from console.log(place) if you want to check what's inside the variable place result and use that as a reference if you want to get other details from the autocomplete result.

Then I just changed your callbacks inside your onLoad and onPlaceChanged props to simply call on to the functions above.

  return (
    <div className="App">
      <div id="searchColumn">
        <h2>Tide Forecast Options</h2>
        <Autocomplete onPlaceChanged={onPlaceChanged} onLoad={onLoad}>
          <input
            type="text"
            placeholder="Search for Tide Information"
            style={{
              boxSizing: `border-box`,
              border: `1px solid transparent`,
              width: `240px`,
              height: `32px`,
              padding: `0 12px`,
              borderRadius: `3px`,
              boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
              fontSize: `14px`,
              outline: `none`,
              textOverflow: `ellipses`
            }}
          />
        </Autocomplete>
      </div>
    </div>
  );

With this, things seems to be working fine.

Here's a code sandbox if you want to try this out (Just use your own API key): https://codesandbox.io/s/react-google-maps-api-multiple-markers-infowindow-forked-dpueyy?file=/src/App.js

Hope this helps.

Upvotes: 11

Related Questions