React Native地图动态定位触发已卸载组件状态更新问题求助
Fixing React Native Map Component Memory Leak Issue
Hey there! Let's tackle that memory leak warning you're seeing with your Map component. The problem happens because the Geolocation.getCurrentPosition call is asynchronous—if your component unloads before this request finishes, its success/failure callbacks will still try to update state or show a Toast, which triggers the "state update on unmounted component" warning and risks memory leaks.
Here's how to fix it step by step:
Key Fixes to Apply
- Track component mount state with a ref: Use a ref to keep track of whether the component is still mounted. This lets us skip callback logic if the component has already unloaded.
- Fix the MapView reference: Your original
let map = nullgets reset on every component render—switch touseRefto keep a stable reference to the MapView instance. - Add a cleanup function in useEffect: This will update our mount state when the component unloads, preventing stale callbacks from running.
Modified Complete Code
import React, { useContext, useState, useEffect, useRef } from 'react'; import { StyleSheet } from 'react-native'; import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps'; import Geolocation from '@react-native-community/geolocation'; import Toast from 'react-native-root-toast'; import { ThemeContext } from '~/utils/theme-context'; import { MAP_STYLE } from '~/utils/map.style'; import { Colors } from '~/styles'; const LATITUDE_DELTA = 0.01; const LONGITUDE_DELTA = 0.01; const Map = props => { const themeContext = useContext(ThemeContext); const mapStyle = MAP_STYLE; // Stable reference for MapView instance const mapRef = useRef(null); // Track if component is still mounted const isMountedRef = useRef(true); let initialRegion = { latitude: 35.78825, longitude: -120.4324, latitudeDelta: 0.015, longitudeDelta: 0.0121, }; const [region, setRegion] = useState(initialRegion); const getCurrentPosition = Geolocation.getCurrentPosition; useEffect(() => { const animate = location => { if (mapRef.current) { mapRef.current.animateToRegion(location, 1000); } }; const getPositionHandler = () => { return getCurrentPosition( info => { // Skip logic if component is unmounted if (!isMountedRef.current) return; const location = { latitude: info.coords.latitude, longitude: info.coords.longitude, latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA, }; animate(location); setRegion(location); }, error => { // Skip Toast if component is unmounted if (!isMountedRef.current) return; Toast.show(error.message, { backgroundColor: Colors.ERROR, textColor: Colors.WHITE, }); }, ); }; getPositionHandler(); // Cleanup: Mark component as unmounted when it's removed return () => { isMountedRef.current = false; }; }, [getCurrentPosition]); return ( <MapView ref={mapRef} provider={PROVIDER_GOOGLE} style={styles.map} customMapStyle={themeContext.theme === 'light' ? [] : mapStyle} region={region}> <Marker coordinate={{ latitude: region.latitude, longitude: region.longitude }} /> </MapView> ); }; const styles = StyleSheet.create({ map: { ...StyleSheet.absoluteFillObject, borderRadius: 24, }, }); export default Map;
What Changed?
isMountedRef: This ref acts as a guard—before any state updates or Toast calls in the Geolocation callbacks, we check if the component is still mounted. If not, we skip the logic entirely.mapRef: Replaced the unstablelet map = nullwith a ref, so we always have access to the correct MapView instance across renders.- Cleanup Function: The
useEffectreturns a function that runs when the component unloads, settingisMountedRef.currenttofalse. This ensures any pending Geolocation callbacks won't try to interact with the unmounted component.
This should eliminate the memory leak warning and keep your component's lifecycle clean!
内容的提问来源于stack exchange,提问作者HexaCrop
相关产品推荐
相关产品推荐

