Search code examples
reactjsgoogle-mapsreact-google-mapsreact-autocomplete

React Google Map and React Places Auto Complete: You have included the Google Maps JavaScript API multiple times on this page


I need to include the google map API twice for my 2 components. Because of that, this error occurs You have included the Google Maps JavaScript API multiple times on this page. I can't remove the first google map API link inside index.html because I need that in my place autocomplete. My problem now is how can I include another google map API link inside the googleMapURL without causing this error?

Google Map Component

const MapWrapped = withScriptjs(withGoogleMap(Map));
<MapWrapped
        googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAP_API_KEY}&v=3.exp&libraries=geometry,drawing,places`}
        loadingElement={<div style={{ height: `100%` }} />}
        containerElement={<div style={{ height: `100%` }} />}
        mapElement={<div style={{ height: `100%` }} />}
      />

Solution

  • You should only have one Google Maps script tag in your code for the Google Maps API to work properly. Since you are using both react-google-maps and place autocomplete, I suggest that you put the Google Map Component with the MapWrapped in the index.js and remove the script tag from your index.html. This way you can only use one script tag. I'm not sure how you are using places autocomplete in your code but if you are using the react-places-autocomplete library, you can do it like the ones in this sample code and code snippet below:

    index.js

    import React, { Component } from 'react';
    import { render } from 'react-dom';
    import { withScriptjs } from 'react-google-maps';
    import Map from './Map';
    
    const App = () => {
      const MapLoader = withScriptjs(Map);
    
      return (
        <MapLoader
          googleMapURL="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
          loadingElement={<div style={{ height: `100%` }} />}
        />
      );
    };
    
    render(<App />, document.getElementById('root'));
    

    Map.js

    mport React, { Component } from 'react';
    import {
      withGoogleMap,
      withScriptjs,
      GoogleMap,
      Marker,
      InfoWindow
    } from 'react-google-maps';
    
    import PlacesAutocomplete, {
      geocodeByAddress,
      getLatLng
    } from 'react-places-autocomplete';
    
    class Map extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          isOpen: false,
          coords: { lat: 40.756795, lng: -73.954298 },
          address: ''
        };
      }
      handleChange = address => {
        this.setState({ address });
      };
    
      handleSelect = address => {
        geocodeByAddress(address)
          .then(results => getLatLng(results[0]))
          .then(latLng =>
            this.setState({
              coords: latLng
            })
          )
          .catch(error => console.error('Error', error));
      };
    
      handleToggleOpen = () => {
        this.setState({
          isOpen: true
        });
      };
    
      handleToggleClose = () => {
        this.setState({
          isOpen: false
        });
      };
    
      render() {
        const GoogleMapExample = withGoogleMap(props => (
          <GoogleMap defaultCenter={this.state.coords} defaultZoom={13}>
            <Marker
              key={this.props.index}
              position={this.state.coords}
              onClick={() => this.handleToggleOpen()}
            >
              {this.state.isOpen && (
                <InfoWindow
                  onCloseClick={this.props.handleCloseCall}
                  options={{ maxWidth: 100 }}
                >
                  <span>This is InfoWindow message!</span>
                </InfoWindow>
              )}
            </Marker>
          </GoogleMap>
        ));
    
        return (
          <div>
            <PlacesAutocomplete
              value={this.state.address}
              onChange={this.handleChange}
              onSelect={this.handleSelect}
            >
              {({
                getInputProps,
                suggestions,
                getSuggestionItemProps,
                loading
              }) => (
                <div>
                  <input
                    {...getInputProps({
                      placeholder: 'Search Places ...',
                      className: 'location-search-input'
                    })}
                  />
                  <div className="autocomplete-dropdown-container">
                    {loading && <div>Loading...</div>}
                    {suggestions.map(suggestion => {
                      const className = suggestion.active
                        ? 'suggestion-item--active'
                        : 'suggestion-item';
                      // inline style for demonstration purpose
                      const style = suggestion.active
                        ? { backgroundColor: '#fafafa', cursor: 'pointer' }
                        : { backgroundColor: '#ffffff', cursor: 'pointer' };
                      return (
                        <div
                          {...getSuggestionItemProps(suggestion, {
                            className,
                            style
                          })}
                          key={suggestion.placeId}
                        >
                          <span>{suggestion.description}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              )}
            </PlacesAutocomplete>
            <GoogleMapExample
              containerElement={<div style={{ height: `500px`, width: '500px' }} />}
              mapElement={<div style={{ height: `100%` }} />}
            />
          </div>
        );
      }
    }
    
    export default Map;