Skip to content
New issue

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

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

Already on GitHub? Sign in 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.

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

No branches or pull requests

7 participants