Search code examples
reactjsgoogle-mapsreact-google-maps

React google maps url undefined


I am trying to update the viewport bounds based on the markers coords in my react google maps component.

However when I call the following line in componentWillMount()

const bounds = new google.maps.LatLngBounds();

I get an error that says google is not defined.

To resolve this I have tried

(1) Adding the google maps script tag to the index.html

(2) Adding the line

/* eslint-disable no-undef */

to the top of my file.

(3) Adding withScriptjs, withGoogleMap inside my compose() but it produces an error that says the googleMapUrl and the loading element is not defined. To solve this I tried doing

    <MapSearchBox
        googleMapURL="https://maps.googleapis.com/maps/api/js?key=APIKEY&v=3.exp&libraries=geometry,drawing,places"
        loadingElement={<div style={{ height: `100%` }} />}
        isMarkerShown={this.state.isMarkerShown}
        onMarkerClick={this.handleMarkerClick}
    />

but this did not work.

(4) Added /* global google */ to the top of my file

Also some other small changes but nothing sticks.

Please give some suggestions!

MapWithASearchBox.js

/* global google */
import React from 'react';
import { get } from 'lodash';
import { compose, withProps, lifecycle, defaultProps } from 'recompose';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
import PropTypes from 'prop-types';
const { SearchBox } = require('react-google-maps/lib/components/places/SearchBox');
import { buildMarkerObj } from '../../../imports/helpers/DataHelpers';

const MapSearchBox = compose(
    withProps(props => ({
        googleMapURL: 'https://maps.googleapis.com/maps/api/js?key=APIKEY=3.exp&libraries=geometry,drawing,places',
        loadingElement: <div style={{ height: `100%` }} />,
        containerElement: <div style={{ height: `450px` }} />,
        mapElement: <div style={{ height: `100%` }} />,
    })),
    withScriptjs,
    withGoogleMap,
    defaultProps({
        externalMarkers: [],
    }),
    lifecycle({
        componentWillMount() {
            const refs = {};
            const { lat, lng } = this.props.coords || (this.props.place && this.props.place.coords) || {};
            const initialMarker = lat !== undefined && lng !== undefined ? [buildMarkerObj({ lat, lng })] : [];
            console.log('THIS PROPS');
            console.log(this.props);
            console.log('PROPS');

            this.setState({
                bounds: null,
                center: {
                    lat: lat || 41.9,
                    lng: lng || -87.624,
                },
                markers: initialMarker,
                injectedMarkers: this.props.markers || [],
                onMapMounted: ref => {
                    refs.map = ref;
                },
                onBoundsChanged: () => {

                },
                onSearchBoxMounted: ref => {
                    refs.searchBox = ref;
                },
                onPlacesChanged: () => {
                    const places = refs.searchBox.getPlaces();

                    places.map(({ address_components, geometry: { location } }) => {
                        this.props.onSetLocation({
                            lat: location.lat(),
                            lng: location.lng(),
                        });
                    });

                    const nextMarkers = places.map(place => ({
                        position: place.geometry.location,
                    }));
                    const nextCenter = get(nextMarkers, '0.position', this.state.center);

                    this.setState({
                        center: nextCenter,
                        markers: nextMarkers,
                    });
                    // refs.map.fitBounds(bounds);
                },
            })
            //ERROR HERE
            const bounds = new google.maps.LatLngBounds();
            this.props.markers.map((marker, index) => {
                bounds.extend(new google.maps.LatLng(
                    marker.coords.lat,
                    marker.coords.lng
                ));
            })

            refs.map.fitBounds(bounds);
            refs.map.panToBounds(bounds);
        },
    }),
)
((props) =>
    <GoogleMap
        ref={props.onMapMounted}
        defaultZoom={15}
        center={props.center}
        onBoundsChanged={props.onBoundsChanged}
    >
        <SearchBox
            ref={props.onSearchBoxMounted}
            bounds={props.bounds}
            controlPosition={google.maps.ControlPosition.TOP_LEFT}
            onPlacesChanged={props.onPlacesChanged}
        >
            <input
                type="text"
                placeholder="Enter your area"
                style={{
                    boxSizing: 'border-box',
                    border: '1px solid white',
                    width: '240px',
                    height: '32px',
                    marginTop: '12px',
                    padding: '0 12px',
                    borderRadius: '3px',
                    boxShadow: '0 2px 6px rgba(0, 0, 0, 0.3)',
                    fontSize: '14px',
                    outline: 'none',
                    textOverflow: 'ellipses',
                    backgroundColor: 'white',
                }}
            />
        </SearchBox>
        {props.markers.map((marker, index) =>
            <Marker key={`map-marker-${index}`} position={marker.position} />
        )}
        {props.externalMarkers.map((marker, index) =>
            <Marker key={`external-marker-${index}`} position={marker.coords} />
        )}
    </GoogleMap>
    )

class MapComponent extends React.PureComponent {

    constructor(props) {
        super(props);
        this.state = { isMarkerShown: false };
    }

    componentDidMount() {
        this.delayedShowMarker();
    }

    componentDidUpdate() {
        console.log('COMPONENT DID UPDATE');
        const bounds = new window.google.maps.LatLngBounds();
        this.props.markers.map((marker, index) => {
            bounds.extend(new window.google.maps.LatLng(
                marker.coords.lat,
                marker.coords.lng
            ));
        })
        refs.map.fitBounds(bounds);
        refs.map.panToBounds(bounds);
    }

    delayedShowMarker = () => {
        setTimeout(() => {
            this.setState({ isMarkerShown: true });
        }, 3000);
    }

    handleMarkerClick = () => {
        this.setState({ isMarkerShown: false });
        this.delayedShowMarker();
    }

    render() {
        return (
            <MapSearchBox
                isMarkerShown={this.state.isMarkerShown}
                onMarkerClick={this.handleMarkerClick}
            />
        );
    }
}

MapComponent.propTypes = {
    className: PropTypes.string,
    latitude: PropTypes.string,
    longitude: PropTypes.string,
    externalMarkers: PropTypes.array,
};

MapComponent.defaultProps = {
    className: '',
    externalMarkers: [],
};

export default MapSearchBox;

Solution

  • Add Google Map url script in index.html

    <script src="https://maps.googleapis.com/maps/api/js?key=APIKEY=3.exp&libraries=geometry,drawing,places></script>