最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to implement Google Maps search box in a React application - Stack Overflow

programmeradmin4浏览0评论

I'm new to React and Google Maps. I'm using google-map-react to integrate Google Maps to my React application. I was able to successfully load the map and add markers.

But I'm getting an error when trying to add the SearchBox. I followed the documentation here SeachBox Documentation and also the issue thread GitHub issue. But still I'm getting the error. What is wrong in this code?

Here is my code

App.js

import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import './App.css';
import Driver from './Driver';
import Passenger from './Passenger';
import SearchBox from './SearchBox';


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      apiReady: false,
      map: null,
      googlemaps: null
    };
  }

  static defaultProps = {
    center: {
      lat: 6.92,
      lng: 79.86
    },
    zoom: 15,
  };

  handleApiLoaded = (map, maps) => {
    // use map and maps objects
    if (map && maps) {
      this.setState({
        apiReady: true,
        map: map,
        googlemaps: maps
      });
    }
  };

  render({ apiReady, googlemaps, map } = this.state) {
    return (
      // Important! Always set the container height explicitly
      <div style={{ height: '100vh', width: '100%' }}>
        <GoogleMapReact
          bootstrapURLKeys={{ key: 'AIzaSyCk7pbkmNhknGumy2vgDykdgVj6lSreTt0', libraries: ['places'] }}
          defaultCenter={this.props.center}
          defaultZoom={this.props.zoom}
          yesIWantToUseGoogleMapApiInternals
          onGoogleApiLoaded={({ map, maps }) => this.handleApiLoaded(map, maps)}
        >
          <Driver
            lat={6.8972152}
            lng={79.8541014}
          />
          <Passenger
            lat={6.9272012}
            lng={79.8681316}
          />

          {apiReady && (<SearchBox
            //  placeholder={"123 anywhere st."}
            //  onPlacesChanged={this.handleSearch} 
            map={map}
            googlemaps={googlemaps} />)}
        </GoogleMapReact>
      </div>
      )
  }
}

export default App

SearchBox.js

import React from 'react';
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

export default class SearchBox extends React.Component {

  static propTypes = {
    placeholder: PropTypes.string,
    onPlacesChanged: PropTypes.func
  }
  render() {
    return <input ref="input" placeholder={this.props.placeholder} type="text"/>;
  }
  onPlacesChanged = () => {
    if (this.props.onPlacesChanged) {
      this.props.onPlacesChanged(this.searchBox.getPlaces());
    }
  }
  ponentDidMount() {
    var input = ReactDOM.findDOMNode(this.refs.input);
    // eslint-disable-next-line no-undef
    this.searchBox = new googlemaps.places.SearchBox(input);
    this.searchBox.addListener('places_changed', this.onPlacesChanged);
  }
  ponentWillUnmount() {
    this.searchBox.removeListener('places_changed', this.onPlacesChanged);
  }

}

// eslint-disable-next-line no-unused-expressions
// eslint-disable-next-line no-lone-blocks
{/* <script defer type="text/javascript" src=";libraries=places"></script> */}

I have pasted the full code because I'm not sure where I went wrong.

I'm new to React and Google Maps. I'm using google-map-react to integrate Google Maps to my React application. I was able to successfully load the map and add markers.

But I'm getting an error when trying to add the SearchBox. I followed the documentation here SeachBox Documentation and also the issue thread GitHub issue. But still I'm getting the error. What is wrong in this code?

Here is my code

App.js

import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import './App.css';
import Driver from './Driver';
import Passenger from './Passenger';
import SearchBox from './SearchBox';


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      apiReady: false,
      map: null,
      googlemaps: null
    };
  }

  static defaultProps = {
    center: {
      lat: 6.92,
      lng: 79.86
    },
    zoom: 15,
  };

  handleApiLoaded = (map, maps) => {
    // use map and maps objects
    if (map && maps) {
      this.setState({
        apiReady: true,
        map: map,
        googlemaps: maps
      });
    }
  };

  render({ apiReady, googlemaps, map } = this.state) {
    return (
      // Important! Always set the container height explicitly
      <div style={{ height: '100vh', width: '100%' }}>
        <GoogleMapReact
          bootstrapURLKeys={{ key: 'AIzaSyCk7pbkmNhknGumy2vgDykdgVj6lSreTt0', libraries: ['places'] }}
          defaultCenter={this.props.center}
          defaultZoom={this.props.zoom}
          yesIWantToUseGoogleMapApiInternals
          onGoogleApiLoaded={({ map, maps }) => this.handleApiLoaded(map, maps)}
        >
          <Driver
            lat={6.8972152}
            lng={79.8541014}
          />
          <Passenger
            lat={6.9272012}
            lng={79.8681316}
          />

          {apiReady && (<SearchBox
            //  placeholder={"123 anywhere st."}
            //  onPlacesChanged={this.handleSearch} 
            map={map}
            googlemaps={googlemaps} />)}
        </GoogleMapReact>
      </div>
      )
  }
}

export default App

SearchBox.js

import React from 'react';
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

export default class SearchBox extends React.Component {

  static propTypes = {
    placeholder: PropTypes.string,
    onPlacesChanged: PropTypes.func
  }
  render() {
    return <input ref="input" placeholder={this.props.placeholder} type="text"/>;
  }
  onPlacesChanged = () => {
    if (this.props.onPlacesChanged) {
      this.props.onPlacesChanged(this.searchBox.getPlaces());
    }
  }
  ponentDidMount() {
    var input = ReactDOM.findDOMNode(this.refs.input);
    // eslint-disable-next-line no-undef
    this.searchBox = new googlemaps.places.SearchBox(input);
    this.searchBox.addListener('places_changed', this.onPlacesChanged);
  }
  ponentWillUnmount() {
    this.searchBox.removeListener('places_changed', this.onPlacesChanged);
  }

}

// eslint-disable-next-line no-unused-expressions
// eslint-disable-next-line no-lone-blocks
{/* <script defer type="text/javascript" src="https://maps.google./maps/api/js?key=AIzaSyCk7pbkmNhknGumy2vgDykdgVj6lSreTt0&libraries=places"></script> */}

I have pasted the full code because I'm not sure where I went wrong.

Share Improve this question edited Apr 10, 2020 at 17:41 geocodezip 161k14 gold badges226 silver badges255 bronze badges asked Apr 10, 2020 at 11:50 zeeezeee 4011 gold badge6 silver badges18 bronze badges 4
  • Please read Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - the summary is that this is not an ideal way to address volunteers, and is probably counterproductive to obtaining answers. Please refrain from adding this to your questions. – halfer Commented Apr 10, 2020 at 11:53
  • Where/how do you load the places library? Please provide a minimal reproducible example that allows to reproduce the issue. – MrUpsidown Commented Apr 10, 2020 at 12:54
  • 1 We also remove "please help me" and "thanks" and all variations thereof. In general, technical writing is preferred here :-). – halfer Commented Apr 10, 2020 at 13:11
  • 1 Your code snippets aren't executable, they should be tagged as just code (fixed) – geocodezip Commented Apr 10, 2020 at 17:41
Add a ment  | 

2 Answers 2

Reset to default 8

google-map-react prop bootstrapURLKeys gives the possibility to avoid inserting script directly to HTML

<GoogleMapReact
    bootstrapURLKeys={{
        key: 'XXXXXXXXXXXXXXXXXXX',
        libraries: 'places'
    }}
......
/>

Also here is a code snippet for Searchbox using hooks (don't forget to memoize onPlacesChanged callback using useCallback in case of parent functional ponent):

const SearchBox = ({ maps, onPlacesChanged, placeholder }) => {
    const input = useRef(null);
    const searchBox = useRef(null);

    const handleOnPlacesChanged = useCallback(() => {
        if (onPlacesChanged) {
            onPlacesChanged(searchBox.current.getPlaces());
        }
    }, [onPlacesChanged, searchBox]);

    useEffect(() => {
        if (!searchBox.current && maps) {
            searchBox.current = new maps.places.SearchBox(input.current);
            searchBox.current.addListener('places_changed', handleOnPlacesChanged);
        }

        return () => {
            if (maps) {
                searchBox.current = null;
                maps.event.clearInstanceListeners(searchBox);
            }
        };
    }, [maps, handleOnPlacesChanged]);

    return <input ref={input} placeholder={placeholder} type="text" />;
};

I figured out the problem in my code. Its a silly mistake that i have made. loading the google maps api shouldn't be done in the SearchBox.js as i have done above. It should be loaded in the inde.html like below in the body. It solved my problem.

 <body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  <script type="text/javascript"
    src="https://maps.googleapis./maps/api/js?key=AIzaSyDjrIzc3Vm83jIb8C-SQhU7JJ5Q-jCJGWg&libraries=places,geometry"></script>
</body>
发布评论

评论列表(0)

  1. 暂无评论