Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Unable to get property 'getPlacePredictions' of undefined or null reference #130

Closed
samdturner opened this issue Apr 29, 2016 · 16 comments
Closed

Comments

@samdturner
Copy link
Contributor

I am seeing this bug periodically with this component. We are using it in production.

The google maps object must have been loaded up because I see that you throw an error in the componentDidMount function if it is not in the window.

Is it possible that the this keyword points to a reference other than the Geosuggest object?

The bug has occurred in the following browsers:

  • Edge 13
  • Chrome Mobile 34
  • Chrome 49
  • IE 10
  • Chrome Mobile 48

Below is the stack trace:

~/react-geosuggest/module/Geosuggest.js in searchSuggests at line 233:0

        options.componentRestrictions = {
          country: this.props.country
        };
      }
      this.autocompleteService.getPlacePredictions(options, function (suggestsGoogle) {
        _this4.updateSuggests(suggestsGoogle || []); // can be null
        if (_this4.props.autoActivateFirstSuggest) {
          _this4.activateSuggest('next');
        }
~/react-geosuggest/module/Geosuggest.js in showSuggests at line 292:0

     */
  }, {
    key: 'showSuggests',
    value: function showSuggests() {
      this.searchSuggests();
      this.setState({ isSuggestsHidden: false });
    }
    /**
     * Hide the suggestions
~/react-geosuggest/module/Geosuggest.js in apply at line 152:0

  }, {
    key: 'onInputFocus',
    value: function onInputFocus() {
      this.props.onFocus();
      this.showSuggests();
    }
    /**
     * When the input gets blurred
     */
@ro-ka
Copy link
Contributor

ro-ka commented May 19, 2016

I suppose your PR was a solution to this issue already?

@samdturner
Copy link
Contributor Author

No, #128 was not a fix for this issue. This bug is unrelated.

@ro-ka
Copy link
Contributor

ro-ka commented May 20, 2016

Do you have some test case? I cannot replicate this…

@samdturner
Copy link
Contributor Author

It's been difficult to reproduce. I am looping in my colleague @olegpesok because I know he has been working on it

@olegpesok
Copy link

@ro-ka Having trouble reproducing with react-test-utils. But I can with the example project in your source:
If I set the following 3 options on the Geosuggest component.

          initialValue='123 Test location'
          autoFocus={true}
          autoActiveFirstSuggest={true}

Full example:

        <Geosuggest
          initialValue='123 Test location'
          autoFocus={true}
          autoActiveFirstSuggest={true}
          fixtures={fixtures}
          onFocus={this.onFocus}
          onBlur={this.onBlur}
          onChange={this.onChange}
          onSuggestSelect={this.onSuggestSelect}
          location={new google.maps.LatLng(53.558572, 9.9278215)}
          radius="20" />

The onInputFocus function fires BEFORE componentDidMount is executed. This causes the "Cannot read property 'getPlacePredictions' of undefined" error.

@ro-ka
Copy link
Contributor

ro-ka commented Jun 21, 2016

Just released in version 1.24.0.

@dragma
Copy link

dragma commented Jun 21, 2016

Since the 1.24.0, I get this error :

Uncaught TypeError: Cannot read property 'getPlacePredictions' of undefined
    searchSuggests @ Geosuggest.js:298
    showSuggests @ Geosuggest.js:388
    Geosuggest._this.onAfterInputChange @ Geosuggest.js:78
    invokeFunc @ index.js:148
    trailingEdge @ index.js:196
    timerExpired @ index.js:183

:)

@Caerostris
Copy link
Contributor

Referencing #172 as this is also connected to server-side rendering. Works fine without.

@Caerostris
Copy link
Contributor

@dragma how can the component render on the client when server-side rendering fails?

@dragma
Copy link

dragma commented Jun 21, 2016

I managed to get this error by doing this trick :

if (typeof window !== 'undefined') {
    return <Geosuggest
        className={classes}
        inputClassName="form-control"
        country="fr"
        fixtures={fixtures}
        types={['(cities)']}
        onSuggestSelect={suggest => console.log('onSuggestSelect', suggest)}
        autoActivateFirstSuggest
        // onSuggestNoResults
        // onChange
    />;
}

A bad idea at least.

@Caerostris
Copy link
Contributor

I've been trying to reproduce this. For all I can tell, the issue discussed here is a result of the workaround you posted above.

@richcsmith
Copy link

I ran into this error today, and what fixed it for me was making sure <Geosuggest /> only rendered after the Google Maps API was instantiated. I'm attaching a <script> tag to the page with a 'load' event listener, then returning a promise that I then use to render the component. Hope this helps someone.

@joevo2
Copy link

joevo2 commented May 16, 2018

@richcsmith im sorry can i have a code example? cant figure out how to hook up the load event listener to the react side of stuff.

im facing this issue as well

@richcsmith
Copy link

richcsmith commented May 16, 2018

@joevo2 here's a quick and dirty example based on some old code I wrote to solve this:

/* utils/window.js */
export function loadScriptAsync(src) {
  const script = window.document.createElement('script')
  script.src = src
  script.async = true
  script.defer = true

  const promise = new Promise((resolve, reject) => {
    script.addEventListener('load', (event) => {
      resolve(event)
    }, false)

    script.addEventListener('error', (error) => reject(error))
  })

  window.document.body.appendChild(script)
  return promise
}
/* lib/google.js */
import { loadScriptAsync } from 'utils/window'

const googleAPIKeys = {
  development: GOOGLE_MAPS_DEV_KEY,
  staging:     GOOGLE_MAPS_STAGING_KEY,
  production:  GOOGLE_MAPS_PROD_KEY,
}

const getGoogleMapsAPIUrl = key => `https://maps.googleapis.com/maps/api/js?key=${key}&libraries=places`
export const initGoogleMapsAPI = () => loadScriptAsync(getGoogleMapsAPIUrl(googleAPIKeys[env]))
/* components/Map/Map.jsx */
import GoogleMap from 'google-map-react'
import Icon from 'components/Icon/Icon'
import { initGoogleMapsAPI } from 'lib/google'

export default class Map extends React.Component {

  state = {
    gMapsLoaded: false,
  }

  componentDidMount = () => {
    if (!window.google) {
      initGoogleMapsAPI().then(() => {
        this.setState({ gMapsLoaded: true })
      })
    }
  }

  render = () => {
    if (!this.state.gMapsLoaded) {
      return null
    }

    const { lat, lng } = this.props.address
    const coordinates = {
      lat: parseFloat(lat),
      lng: parseFloat(lng),
    }

    return (
      <GoogleMap center={coordinates} zoom={14}>
        <Icon name="location-pin" {...coordinates} />
      </GoogleMap>
    )
  }
}

Edit: It's been a while since I last used this library—I just realized that this issue is for Geosuggest, and not google-map-react, but the idea is still the same.

For this, I created an <AddressInput /> component that wrapped <Geosuggest />, and rendered a standard input (styled the same) if window.google wasn't available, then rendered the <Geosuggest /> component after it loaded.

@joevo2
Copy link

joevo2 commented May 16, 2018

@richcsmith thanks! thats interesting, basically creating the script on react side hmm... Would something like prefetch on the html script tag work?

@richcsmith
Copy link

richcsmith commented May 20, 2018

@joevo2 I think it would! In my project, I had several components that each depended on the Google Maps API in different areas on the app (sometimes, on the same page), so I had to check for its existence before attempting to load it.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants