[英]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:不支持,您需要为此考虑不同的选项:
<script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places"></script>
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.