在React中使用Google Place Autocomplete API

时间:2018-10-20 16:40:27

标签: javascript reactjs google-maps-api-3

我想在我的react组件中有一个自动完成位置搜索栏,但是不知道如何实现它。 documentation说要包含

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap" async defer></script>

在HTML文件中,然后有一个指向某个元素的初始化函数-我该如何使用我的react组件/ JSX来做到这一点?我想我必须导入api链接,但是我不知道从那里去哪里。

import React from 'react';
import "https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places&callback=initMap";

const SearchBar = () => (   
    <input type="text" id="search"/> //where I want the google autocomplete to be
);

export default SearchBar;

3 个答案:

答案 0 :(得分:5)

通过静态import加载Google Maps API:

import "https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places&callback=initMap";

不受支持,为此您需要考虑其他选项:

  • 通过/public/index.html文件引用Google Maps API JS库: <script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>
  • 动态动态加载JS资源,例如使用this library

现在有关SearchBar组件,以下示例演示了如何基于this official example实现 Place Autocomplete 的简单版本(不依赖于Google Map实例)

import React from "react";
/* global google */


class SearchBar extends React.Component {
  constructor(props) {
    super(props);
    this.autocompleteInput = React.createRef();
    this.autocomplete = null;
    this.handlePlaceChanged = this.handlePlaceChanged.bind(this);
  }

  componentDidMount() {
    this.autocomplete = new google.maps.places.Autocomplete(this.autocompleteInput.current,
        {"types": ["geocode"]});

    this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
  }

  handlePlaceChanged(){
    const place = this.autocomplete.getPlace();
    this.props.onPlaceLoaded(place);
  }



  render() {
    return (
        <input ref={this.autocompleteInput}  id="autocomplete" placeholder="Enter your address"
         type="text"></input>
    );
  }
}

Here is a demo

答案 1 :(得分:0)

使注册表格的自定义地址自动完成并遇到了一些问题,

// index.html imports the google script via script tag  ie: <script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>


import {useState, useRef, useEffect } from 'React'

function AutoCompleteInput(){

const [predictions, setPredictions] = useState([]);
const [input, setInput] = useState('');
const [selectedPlaceDetail, addSelectedPlaceDetail] = useState({})
const predictionsRef = useRef();


useEffect(
()=>{
      try {
        autocompleteService.current.getPlacePredictions({ input }, predictions => {
          setPredictions(predictions);
        });
      } catch (err) {
       // do something
      }
    }
}, [input])

const handleAutoCompletePlaceSelected = placeId=>{
 if (window.google) {
      const PlacesService = new window.google.maps.places.PlacesService(predictionsRef.current);
      try {
        PlacesService.getDetails(
          {
            placeId,
            fields: ['address_components'],
          },
         place => addSelectedPlaceDetail(place)
        );
      } catch (e) {
        console.error(e);
      }
    }
}

return (
  <>
   <input onChange={(e)=>setInput(e.currentTarget.value)}
    <div ref={predictionsRef}
     { predictions.map(prediction => <div onClick={ ()=>handleAutoCompletePlaceSelected(suggestion.place_id)}> prediction.description </div> )
   }
   </div>
  <>
 )
}

因此,基本上,您可以设置自动完成呼叫,并以本地状态获取预测结果。

从此处映射并显示带有单击处理程序的结果,该处理程序将对places服务发出后续请求,并可以访问完整地址对象或所需的任何字段的getDetails方法。

然后将响应保存到本地状态,然后退出。

答案 2 :(得分:0)

这是一个使用 ES6 + React Hooks 的解决方案:

首先,创建一个 useGoogleMapsApi 钩子来加载外部脚本:

import { useEffect, useState, useCallback } from 'react'
import loadScript from 'load-script'
import each from 'lodash/each'

var googleMapsApi
var loading = false
var callbacks = []

const useGoogleMapsApi = () => {
  const [, setApi] = useState()

  const callback = useCallback(() => {
    setApi(window.google.maps)
  }, [])

  useEffect(() => {
    if (loading) {
      callbacks.push(callback)
    } else {
      if (!googleMapsApi) {
        loading = true
        loadScript(
          `https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&libraries=places`,
          { async: true },
          () => {
            loading = false
            googleMapsApi = window.google.maps
            setApi(window.google.maps)
            each(callbacks, init => init())
            callbacks = []
          })
      }
    }
  }, [])

  return googleMapsApi
}

export default useGoogleMapsApi

然后,这是您的输入组件:

import React, { useRef, useEffect, forwardRef } from 'react'
import useGoogleMapsApi from './useGoogleMapsApi'

const LocationInput = forwardRef((props, ref) => {
  const inputRef = useRef()
  const autocompleteRef = useRef()
  const googleMapsApi = useGoogleMapsApi()

  useEffect(() => {
    if (googleMapsApi) {
      autocompleteRef.current = new googleMapsApi.places.Autocomplete(inputRef.current, { types: ['(cities)'] })
      autocompleteRef.current.addListener('place_changed', () => {
        const place = autocompleteRef.current.getPlace()
        // Do something with the resolved place here (ie store in redux state)
      })
    }
  }, [googleMapsApi])

  const handleSubmit = (e) => {
    e.preventDefault()
    return false
  }

  return (
    <form autoComplete='off' onSubmit={handleSubmit}>
      <label htmlFor='location'>Google Maps Location Lookup</label>
      <input
        name='location'
        aria-label='Search locations'
        ref={inputRef}
        placeholder='placeholder'
        autoComplete='off'
      />
    </form>
  )
}

export default LocationInput

中提琴!