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

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 = null gets reset on every component render—switch to useRef to 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 unstable let map = null with a ref, so we always have access to the correct MapView instance across renders.
  • Cleanup Function: The useEffect returns a function that runs when the component unloads, setting isMountedRef.current to false. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:22:46