react-native-google-places-autocomplete报错:request has not been opened求助
react-native-google-places-autocomplete 偶发报错:request has not been opened
问题描述
点击react-native-google-places-autocomplete组件的列表项时,偶发request has not been opened错误,导致应用崩溃,有时能正常运行。已查阅官方文档及仓库Issues,使用组件提供的onFail方法未捕获到任何错误信息。
错误截图

代码实现
import React, { useEffect, useRef, useState } from 'react' import { ActivityIndicator, Image, Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native' import MapView, { Callout, Marker, PROVIDER_GOOGLE } from 'react-native-maps'; import colors from '../theme/colors' import { appConstants, extraConstants } from '../utils/constants'; import { SubmitButton } from './Button'; import { responsiveHeight, responsiveWidth } from '../utils/responsive_Dimensions'; import { NavigationHeader } from './Header'; import images from '../theme/images'; import { useDispatch, useSelector } from 'react-redux'; import { getGeoCodeAddress, getUserCurrentLocation } from '../utils/commonMethods'; import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete'; import { setUserLocation } from '../store/slice/userSlice'; const MapModal = ({ onExit, onSubmit }: any) => { const mapref = useRef<any>() const googleAutocompleteRef = useRef<any>() const userLocation: any = useSelector((state: any) => state?.userReducer.userLocation); const dispatch = useDispatch() const [pinLocation, setPinLocation] = useState({ latitude: 0, longitude: 0 }) const [fetchingCurrentLocation, setFetchingCurrentLocation] = useState(false) const [isFetchingAddress, setIsFetchingAddress] = useState(false) const [initialRegion, setInitialRegion] = useState({ latitude: 0, longitude: 0, latitudeDelta: 0.08, longitudeDelta: 0.08, }) useEffect(() => { setPinLocation({ latitude: userLocation.lat, longitude: userLocation.lng }) setInitialRegion((prevData: any) => { return { ...prevData, latitude: userLocation.lat, longitude: userLocation.lng } }) }, []) const onDragEnd = async (event: any) => { let coordinates = event.nativeEvent.coordinate setPinLocation(coordinates) } const _onSubmit = async () => { let geoAddress: any = await getGeoCodeAddress({ lat: pinLocation.latitude, lng: pinLocation.longitude }) dispatch(setUserLocation({ lat: pinLocation.latitude, lng: pinLocation.longitude, geoAddress: geoAddress })) setTimeout(() => { setIsFetchingAddress(false) onExit() }, 300); } const animateToRegion = (latitude: any, longitude: any) => { mapref?.current?.animateToRegion({ latitude, longitude, latitudeDelta: 0.08, longitudeDelta: 0.08 }, 3000) } const setCurrentLocation = () => { setFetchingCurrentLocation(true) getUserCurrentLocation().then((myLocation: any) => { animateToRegion(myLocation?.lat, myLocation?.lng) }).finally(() => { setFetchingCurrentLocation(false) }) } const GooglePlacesAutocompleteCrossButton = () => { return ( <TouchableOpacity style={styles.googlePlacesAutocompleteCrossButton} onPress={() => { googleAutocompleteRef?.current?.setAddressText("") googleAutocompleteRef?.current?.clear() }}> <Image source={images.close} style={styles.googlePlacesAutocompleteCrossIcon} /> </TouchableOpacity> ) } return ( <Modal visible={true} animationType='slide' onRequestClose={onExit}> <View style={styles.container}> <View style={styles.googlePlacesAutocomplete}> <GooglePlacesAutocomplete placeholder={appConstants?.searchLocation} ref={googleAutocompleteRef} renderRightButton={() => <GooglePlacesAutocompleteCrossButton />} fetchDetails={true} onPress={(data, details: any = null) => { let { lat, lng } = details?.geometry?.location lat && lng && animateToRegion(lat, lng) }} onFail={(err) => { console.log("GooglePlacesAutocomplete - error -> ", err); }} query={{ key: extraConstants.myApiKey, language: 'en', }} /> </View> <NavigationHeader isFloating={true} onBackPress={onExit} title={appConstants.selectLocation} /> {initialRegion.latitude != 0 && initialRegion.longitude != 0 && <MapView style={styles.mapContainer} ref={mapref} onRegionChange={(coords) => { googleAutocompleteRef?.current?.blur() setPinLocation({ latitude: coords.latitude, longitude: coords.longitude }) }} initialRegion={initialRegion}> <Marker coordinate={pinLocation} draggable={true} onDragEnd={onDragEnd} pinColor='red' /> </MapView>} <SubmitButton isLoading={isFetchingAddress} style={styles.submitButton} activeOpacity={1} title={appConstants.submit} onPressIn={() => { setIsFetchingAddress(true) }} onPress={onSubmit ? async () => { let geoAddress: any = await getGeoCodeAddress({ lat: pinLocation.latitude, lng: pinLocation.longitude }) onSubmit({ lat: pinLocation.latitude, lng: pinLocation.longitude, geoAddress: geoAddress }) setTimeout(() => { setIsFetchingAddress(false) }, 300); } : _onSubmit} /> <TouchableOpacity style={styles.myLocationBtn} activeOpacity={0.9} onPress={setCurrentLocation}> { fetchingCurrentLocation ? (<ActivityIndicator style={styles.myLocationIcon} color={colors.mainTheme} />) : (<Image source={images.myLocation} style={styles.myLocationIcon} />) } </TouchableOpacity> </View> </Modal > ) } export default MapModal
可能的解决方案
- 添加异常捕获与参数校验:在
onPress回调中增加try-catch和参数判断,避免无效数据导致的异常:onPress={(data, details: any = null) => { try { if (!details?.geometry?.location) return; const { lat, lng } = details.geometry.location; animateToRegion(lat, lng); } catch (err) { console.error('GooglePlacesAutocomplete onPress异常:', err); } }} - 调整地图区域变化时的模糊时机:避免在请求过程中强制模糊打断请求,增加延迟:
onRegionChange={(coords) => { setPinLocation({ latitude: coords.latitude, longitude: coords.longitude }); setTimeout(() => { googleAutocompleteRef?.current?.blur(); }, 500); }} - 添加请求防抖:给
GooglePlacesAutocomplete组件添加debounce={300}属性,减少频繁请求引发的异常 - 监听Modal状态:在Modal的
visible状态变化时,重置自动补全组件的状态,避免组件未就绪时触发请求
内容的提问来源于stack exchange,提问作者Harpreet Singh - React Native
相关产品推荐
相关产品推荐

