【问题标题】:Using Google Place Autocomplete API in React在 React 中使用 Google Place Autocomplete API
【发布时间】:2019-03-25 06:14:49
【问题描述】:

我想在我的 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;

【问题讨论】:

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


    【解决方案1】:

    通过静态 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 库: &lt;script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&amp;libraries=places"&gt;&lt;/script&gt;
    • 动态加载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>
        );
      }
    }
    

    【讨论】:

    • 当我这样做时,我收到错误google' is not defined no-undef。根据演示,我将 google api 脚本(使用我自己的密钥)放在我的 public/index.html 文件中,但它仍然无法识别 google。不知何故它不是全球性的?
    • @Adam.V,您可能忘记将/* global google */ 放在文件顶部。或者可以使用this solution。它还包含为什么会发生此错误的解释
    • 你看准了!我看到了灰色的文字,并认为这只是一个评论。我不知道它在 js 中有什么用途。
    【解决方案2】:

    正在为注册表单制作自定义地址自动填充功能并遇到了一些问题,

    // 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>
      <>
     )
    }
    

    因此,基本上,您设置了自动完成调用,并以您的本地状态取回预测结果。

    从那里,使用单击处理程序映射并显示结果,该处理程序将对场所服务执行后续请求,并可以访问完整地址对象或您想要的任何字段的 getDetails 方法。

    然后,您将该响应保存到您当地的州,然后出发。

    【讨论】:

      【解决方案3】:

      这是一个使用 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
      
      

      维奥拉!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-14
        • 2020-08-10
        • 2019-03-15
        • 1970-01-01
        • 2017-08-31
        • 1970-01-01
        • 2017-01-15
        • 1970-01-01
        相关资源
        最近更新 更多