简体   繁体   English

在 React 中使用 Google Place Autocomplete API

[英]Using Google Place Autocomplete API in React

I want to have an auto completing location search bar in my react component, but don't know how I would go about implementing it.我想在我的 React 组件中有一个自动完成的位置搜索栏,但不知道我将如何实现它。 The documentation says to include文件说包括

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

in an HTML file, and then have an initialize function pointing to an element - how would I go about doing this with my react component/JSX?在一个 HTML 文件中,然后有一个指向一个元素的初始化函数 - 我将如何使用我的 React 组件/JSX 执行此操作? I presume I would have to import the api link, but I have no clue where to go from there.我想我必须导入 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;

Google Maps API loading via static import :通过静态import加载 Google Maps API:

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

is not supported, you need to consider a different options for that purpose:不支持,您需要为此考虑不同的选项:

  • reference Google Maps API JS library via /public/index.html file: <script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>通过 /public/index.html 文件引用 Google Maps API JS 库: <script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>
  • or dynamically load JS resource, for example using this library或者动态加载 JS 资源,例如使用这个库

Now regarding SearchBar component, the below example demonstrates how to implement a simple version of Place Autocomplete (without a dependency to Google Map instance) based on this official example现在关于SearchBar组件,下面的示例演示了如何基于此官方示例实现一个简单版本的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>
    );
  }
}

Was making a custom address autocomplete for a sign up form and ran into some issues,正在为注册表单制作自定义地址自动完成功能并遇到一些问题,

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

So basically, you setup the autocomplete call, and get back the predictions results in your local state.所以基本上,您设置自动完成调用,并在您的本地状态中获取预测结果。

from there, map and show the results with a click handler that will do the follow up request to the places services with access to the getDetails method for the full address object or whatever fields you want.从那里,使用单击处理程序映射并显示结果,该处理程序将对地点服务执行后续请求,并访问完整地址对象或您想要的任何字段的 getDetails 方法。

you then save that response to your local state and off you go.然后,您将该响应保存到您的本地状态,然后您就可以开始了。

Here's a solution using ES6 + React Hooks:这是使用 ES6 + React Hooks 的解决方案:

First, create a useGoogleMapsApi hook to load the external script:首先,创建一个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

Then, here's your input component:然后,这是您的输入组件:

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

Viola!中提琴!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM