React/Material UI - Google Places 自动完成下拉菜单有时不起作用
Posted
技术标签:
【中文标题】React/Material UI - Google Places 自动完成下拉菜单有时不起作用【英文标题】:React/Material UI - Google Places autocomplete dropdown sometimes doesn't work 【发布时间】:2022-01-22 17:58:39 【问题描述】:所以这段代码可以工作,但有时在页面加载或刷新谷歌地方下拉自动完成建议时没有显示,我可以在搜索框中输入任何内容,但它只是不加载自动完成框。什么可能导致此问题?
这是代码。
const apiKey = process.env.REACT_APP_GOOGLE_KEY;
const mapApiJs = 'https://maps.googleapis.com/maps/api/js';
const geocodeJson = 'https://maps.googleapis.com/maps/api/geocode/json';
// load google map api js
function loadAsyncScript(src)
return new Promise(resolve =>
const script = document.createElement("script");
Object.assign(script,
type: "text/javascript",
async: true,
src
)
script.addEventListener("load", () => resolve(script));
document.head.appendChild(script);
)
const extractAddress = (place) =>
const address =
city: "",
state: "",
zip: "",
country: "",
plain()
const city = this.city ? this.city + ", " : "";
const zip = this.zip ? this.zip + ", " : "";
const state = this.state ? this.state + ", " : "";
return city + zip + state + this.country;
if (!Array.isArray(place?.address_components))
return address;
if(typeof place.geometry.location.lat === 'function')
address.lat = place.geometry.location.lat();
else
address.lat = place.geometry.location.lat;
if(typeof place.geometry.location.lng === 'function')
address.lng = place.geometry.location.lng();
else
address.lng = place.geometry.location.lng;
place.address_components.forEach(component =>
const types = component.types;
const value = component.long_name;
if (types.includes("locality"))
address.city = value;
if (types.includes("administrative_area_level_2"))
address.state = value;
if (types.includes("postal_code"))
address.zip = value;
if (types.includes("country"))
address.country = value;
);
return address;
function ReportForm()
const searchInput = useRef(null);
const [address, setAddress] = useState();
const [coords, setCoords] = useState(
lat: 42.680115925419294,
lng: 14.010667884881462,
);
// init gmap script
const initMapScript = () =>
// if script already loaded
if(window.google)
return Promise.resolve();
const src = `$mapApiJs?key=$apiKey&libraries=places&v=weekly`;
return loadAsyncScript(src);
// do something on address change
const onChangeAddress = (autocomplete) =>
const place = autocomplete.getPlace();
setAddress(extractAddress(place));
setCoords(
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
);
// init autocomplete
const initAutocomplete = () =>
if (!searchInput.current) return;
const autocomplete = new window.google.maps.places.Autocomplete(searchInput.current);
autocomplete.setFields(["address_component", "geometry"]);
autocomplete.addListener("place_changed", () => onChangeAddress(autocomplete));
const reverseGeocode = ( latitude: lat, longitude: lng) =>
const url = `$geocodeJson?key=$apiKey&latlng=$lat,$lng`;
searchInput.current.value = "Getting your location...";
fetch(url)
.then(response => response.json())
.then(location =>
const place = location.results[0];
const _address = extractAddress(place);
setAddress(_address);
searchInput.current.value = _address.plain();
setCoords(
lat: lat,
lng: lng,
);
)
const findMyLocation = () =>
if (navigator.geolocation)
navigator.geolocation.getCurrentPosition(position =>
reverseGeocode(position.coords)
)
// load map script after mounted
useEffect(() =>
initMapScript().then(() => initAutocomplete())
, []);
return(
<>
<form>
<div>
<div className="search">
<span><Search /></span>
<input
name="address"
ref=searchInput
type="text"
placeholder="Search Address...."
/>
<button type="button" onClick=findMyLocation><GpsFixed /></button>
</div>
</div>
</form>
</>
);
我也尝试过使用 Material UI TextField
和 inputRef
而不是标准的 input
,但我遇到了同样的问题。此外,它在页面刷新时更频繁地发生。在第一页加载时,它几乎每次都能正常工作。
【问题讨论】:
【参考方案1】:您是否尝试将searchInput.current
添加到useEffect
的依赖数组中?您在initAutocomplete
中有这条线if (!searchInput.current) return;
,并且您的searchInput
最初设置为null
。因此,在页面刷新时,在输入元素上设置的 ref
与 initAutocomplete
函数的运行之间可能存在竞争条件。
【讨论】:
以上是关于React/Material UI - Google Places 自动完成下拉菜单有时不起作用的主要内容,如果未能解决你的问题,请参考以下文章
来自不同组件的 React + Material-UI 样式类在静态服务时发生冲突
React - Material-UI Accordion:如何使标题居中并展开图标