Adrian Pascu
Adrian Pascu

Reputation: 1039

ReactJs external script - Google Maps

I am trying to add Google Maps to a ReactJs web app, but without any success.

I know there are some react components that wrap google maps, but they don't suit my actual needs so I have to build one myself. My problem is that I don't know how to handle the script tag required by google maps to work : <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD6maRCH9aI1K0sWA_FRdjIQv9AJgP7aQ0&callback=initMap" async defer></script>

I put it in index.html at first, but I get this error when I start my app in the chrome devtools :

Uncaught (in promise) 
Hc {message: "initMap is not a function", name: "InvalidValueError", stack: "Error↵    at new Hc (https://maps.googleapis.com/m…I1K0sWA_FRdjIQv9AJgP7aQ0&callback=initMap:124:108"}

I've tried using fetch() to get the script, see what it actually is, but it ask for a CORS header and thinking I don't know the exact params that this request expects I think this is not the solution.

Upvotes: 0

Views: 1692

Answers (2)

Dave Kalu
Dave Kalu

Reputation: 1595

As @Naismith said the error is as a result of the callback=initMap within your google maps script include. So for it to work, you would have to implement the initMap function like so:

<div id="map"></div>
    <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.397, lng: 150.644},
          zoom: 8
        });
      }
    </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>

Except you're trying to display the maps within a component, in that case you can try this approach where you create a promise for the Google Maps API, and resolve that promise in a (global) callback function the Google Maps API can run. In your component code you'd then wait for the promise to be resolved before proceeding.

class Map extends React.Component {
  getGoogleMaps() {
    if (!this.googleMapsPromise) {
      this.googleMapsPromise = new Promise((resolve) => {
        // Add a global handler for when the API finishes loading
        window.resolveGoogleMapsPromise = () => {
          // Resolve the promise
          resolve(google);

          // Tidy up
          delete window.resolveGoogleMapsPromise;
        };

        // Load the Google Maps API
        const script = document.createElement("script");
        const API = 'AIzaSyDbAz1XXxDoKSU2nZXec89rcHPxgkvVoiw';
        script.src = `https://maps.googleapis.com/maps/api/js?key=${API}&callback=resolveGoogleMapsPromise`;
        script.async = true;
        document.body.appendChild(script);
      });
    }

    // Return a promise for the Google Maps API
    return this.googleMapsPromise;
  }

  componentWillMount() {
    // Start Google Maps API loading since we know we'll soon need it
    this.getGoogleMaps();
  }

  componentDidMount() {
    // Once the Google Maps API has finished loading, initialize the map
    this.getGoogleMaps().then((google) => {
      const uluru = {lat: -25.366, lng: 131.044};
      const map = new google.maps.Map(document.getElementById('map'), {
        zoom: 4,
        center: laos
      });
      const marker = new google.maps.Marker({
        position: laos,
        map: map
      });
    });
  }

  render() {
    return (
      <div>
        <div id="map" style={{width: 600, height: 300}}></div>
      </div>
    )
  }
}

ReactDOM.render(
  <Map/>,
  document.getElementById('react')
);

Upvotes: 1

Naismith
Naismith

Reputation: 266

The reason you're getting initMap is not a function, is because apart of the script's src that you provided at the end is 'callback=initMap'. This will run a function called initMap after the script has finished loading.

If you looked at the documentation on Google's website they have an example function that you would have to put in above your script tag for google maps.

https://developers.google.com/maps/documentation/javascript/tutorial

Upvotes: 0

Related Questions