You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级至Expo SDK 51后React Native Maps使用PROVIDER_DEFAULT崩溃

Expo SDK 51升级后React Native Maps异常排查与解决

问题描述

升级Expo SDK 51后,React Native Maps出现两处异常:

  • 使用PROVIDER_DEFAULT时应用直接崩溃
  • 使用PROVIDER_GOOGLE时iOS端抛出错误:ERROR react-native-maps: AirGoogleMaps dir must be added to your xCode project to support GoogleMaps on iOS.

项目中结合BottomSheetModal实现地图内搜索功能,核心代码片段如下:

var mapStyle = [
    {
      "elementType": "geometry",
      "stylers": [
        {
          "color": "#f5f5f5"
        }
      ]
    },
    // 省略其余地图样式配置
    {
      "featureType": "water",
      "elementType": "labels.text.fill",
      "stylers": [
        {
          "color": "#9e9e9e"
        }
      ]
    }
  ]

//SetLocation Modal state
const [searchLocationModal, setSearchLocationModal] = useState(false);

const [isLoading, setIsLoading] = useState(false);

//geoLocation state
const { userLocation } = useSnapshot(locationState);

const DELTA_VALUE = 0.005

const initialRegion = {
    latitude: locationState.latitude,
    longitude: locationState.longitude,
    latitudeDelta: 0.005,
    longitudeDelta: 0.005,
}

const [markerLocation, setMarkerLocation] = useState({
    latitude: locationState.latitude,
    longitude: locationState.longitude,
    latitudeDelta: DELTA_VALUE,
    longitudeDelta: DELTA_VALUE,
})

const sheetRef = useRef<BottomSheet>(null)
//Second SnapPoint 45%
const snapPoints = ['38%', '38%']

const [addressSearch, setAddressSearch] = useState('');

const updateLocation = async () => {

    let currentUserID = firebase.default.auth().currentUser?.uid

    try {  
      if(currentUserID){
          await updateUser(currentUserID).then((doc) => {

              //Check if markerLocation is the same as saved LatLng
              doc.get().then((userDoc) => {
                  if (markerLocation.latitude != userDoc.data().location.lat && markerLocation.longitude != userDoc.data().location.long ){
                      doc.update({
                          "location.lat": markerLocation.latitude,
                          "location.long": markerLocation.longitude,
                      }).then(async () => {
                          await getSavedLocation().then(() => {setSearchLocationModal(false)})
                      })
                  } else {
                      console.log('Location is the same')
                  }
                       
              }).then(() => {
                findNearestPopular()
              })
          })
      } else {
        locationState.latitude = markerLocation.latitude
        locationState.longitude = markerLocation.longitude

        await getAddress({lat: markerLocation.latitude, long: markerLocation.longitude}).then(() => {
          setSearchLocationModal(false)
          console.log(locationState)
        }).then(() => {
          findNearestPopular()
        })            
      }
    } catch (error) {
      console.log(error.message)
    }
}

useEffect(() => {
    
    const timer = setTimeout(() => {
        if(addressSearch == ''){
            setMarkerLocation(initialRegion)
        } else 
        getLatLang(addressSearch).then((x) => {
            console.log('Bottom Sheet result: ' + x?.lat, x?.long)
            if (x?.lat && x?.long != undefined) {
                setMarkerLocation({
                    latitude: x?.lat,
                    longitude: x?.long,
                    latitudeDelta: DELTA_VALUE,
                    longitudeDelta: DELTA_VALUE
                })
            }

        })
    },500)

    return () => {clearTimeout(timer)}
  }, [locationState, addressSearch])

return (
    <>
    <Modal
    animationType="slide"
    visible={searchLocationModal}
    onRequestClose={() => {
        setSearchLocationModal(!searchLocationModal);
    }}
    >

<TouchableOpacity style={styles.modalCloseBtn} onPress={() => {setSearchLocationModal(!searchLocationModal)}}>
      <Entypo name="chevron-small-left" size={30} color="#37BD6B"/>
</TouchableOpacity>

    <MapView.Animated
    style={{height: '70%', width: '100%', zIndex: -1}}
    mapType={"standard"}
    provider={PROVIDER_DEFAULT}
        initialRegion={initialRegion}
        region={markerLocation}
        customMapStyle={mapStyle}
        
    >
        <Marker.Animated coordinate={markerLocation}></Marker.Animated>
    </MapView.Animated>
        <BottomSheet keyboardBehavior="interactive" ref={sheetRef} snapPoints={snapPoints} style={{}}>
        
            <React.Fragment>
                <View style={styles.currentLocationContainer}>
                    <View>
                        <MaterialIcons style={styles.locationIcon} name={'my-location'} size={25}/>
                    </View>
                    <View style={styles.currentLocationTxtGrp}>
                        <View>
                            <Text style={{fontWeight: '700', fontSize: 18, fontFamily: 'Gilroy-SemiBold', marginBottom: 4}}>Current Location</Text>
                        </View>
                            
                        <View>
                            <Text style={{fontWeight: '400', fontSize: 16, fontFamily: 'Gilroy-Medium'}}>{userLocation}</Text>
                        </View>
                    </View>
                </View>

                <View style={styles.searchContainer}>
                    <View style={styles.searchIconContainer}>
                        <AntDesign style={{paddingLeft: 15, color: "#B3B4B9"}} name="search1" size={19} />
                    </View>

                    <BottomSheetTextInput onChangeText={(value) => setAddressSearch(value)} style={styles.searchBar}/>
                </View>

                
                <TouchableOpacity onPress={updateLocation} >
                    <View style={styles.updateLocationContainer}>
                        <Text style={styles.updateLocation}>Update Location</Text>
                    </View>
                </TouchableOpacity>
                
            </React.Fragment>   
        </BottomSheet>

    </Modal>
)

解决方案

一、修复PROVIDER_DEFAULT崩溃问题

  1. 适配依赖版本:Expo SDK 51对应React Native 0.74,需安装适配的react-native-maps版本(建议^1.14.0及以上):
npx expo install react-native-maps@latest
  1. 配置位置权限:在app.json/app.config.js中补充位置权限声明:
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSLocationWhenInUseUsageDescription": "需要访问您的位置以显示地图"
      }
    },
    "android": {
      "permissions": ["ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION"]
    }
  }
}
  1. 清除缓存重建:
npx expo prebuild --clean
npx expo run:ios
npx expo run:android

二、解决Google Maps iOS端报错问题

Expo managed workflow下无法手动操作Xcode项目添加AirGoogleMaps目录,推荐使用官方适配的expo-google-maps:

  1. 安装依赖:
npx expo install expo-google-maps
  1. 替换组件导入:将原react-native-maps的MapView替换为expo-google-maps的组件:
// 移除旧导入
// import MapView, { Marker } from 'react-native-maps';
import { MapView, Marker } from 'expo-google-maps';
  1. 配置API密钥:在app.json中添加Google Maps API密钥:
{
  "expo": {
    "ios": {
      "googleMapsApiKey": "你的iOS端Google Maps API密钥"
    },
    "android": {
      "googleMapsApiKey": "你的Android端Google Maps API密钥"
    }
  }
}

三、额外注意事项

  • 若必须使用原生react-native-maps的Google Maps provider,需切换到bare workflow,手动在Xcode中添加react-native-maps包内的AirGoogleMaps目录,并配置API密钥。
  • 检查BottomSheet与MapView的层级:确保zIndex设置合理,避免交互冲突或视图遮挡。

内容的提问来源于stack exchange,提问作者CodingJunkie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 08:49:49