diff --git a/docs/examples.json b/docs/examples.json
index d0392162e..ccaf59dc8 100644
--- a/docs/examples.json
+++ b/docs/examples.json
@@ -260,6 +260,16 @@
         "relPath": "Map/MapAndRNNavigation.js",
         "name": "MapAndRNNavigation"
       },
+      {
+        "metadata": {
+          "title": "Map (un-)mount",
+          "tags": [],
+          "docs": "\nShowing and hiding the the map should not lead to increased memory consumption, use this example to check it on the profiler.\n"
+        },
+        "fullPath": "example/src/examples/Map/MapUnMount.tsx",
+        "relPath": "Map/MapUnMount.tsx",
+        "name": "MapUnMount"
+      },
       {
         "metadata": {
           "title": "Offline Example",
diff --git a/example/src/examples/Map/MapUnMount.tsx b/example/src/examples/Map/MapUnMount.tsx
new file mode 100644
index 000000000..1d4882181
--- /dev/null
+++ b/example/src/examples/Map/MapUnMount.tsx
@@ -0,0 +1,51 @@
+import React, { useState, useEffect } from 'react';
+import Mapbox from '@rnmapbox/maps';
+import { Button } from '@rneui/base';
+
+import sheet from '../../styles/sheet';
+import { ExampleWithMetadata } from '../common/ExampleMetadata'; // exclude-from-doc
+
+const MapUnMount = () => {
+  const [isMounted, setIsMounted] = useState(true);
+
+  useEffect(() => {
+    Mapbox.locationManager.start();
+
+    return (): void => {
+      Mapbox.locationManager.stop();
+    };
+  }, []);
+
+  return (
+    <>
+      <Button
+        onPress={() => setIsMounted((mounted) => !mounted)}
+        title={isMounted ? 'unmount MapView' : 'mount MapView'}
+      />
+      {isMounted ? (
+        <Mapbox.MapView
+          styleURL={Mapbox.StyleURL.Dark}
+          style={sheet.matchParent}
+          testID={'show-map'}
+        >
+          <Mapbox.Camera followZoomLevel={12} followUserLocation />
+
+          <Mapbox.UserLocation />
+        </Mapbox.MapView>
+      ) : null}
+    </>
+  );
+};
+
+export default MapUnMount;
+
+/* end-example-doc */
+
+const metadata: ExampleWithMetadata['metadata'] = {
+  title: 'Map (un-)mount',
+  tags: [],
+  docs: `
+Showing and hiding the the map should not lead to increased memory consumption, use this example to check it on the profiler.
+`,
+};
+MapUnMount.metadata = metadata;
diff --git a/example/src/examples/Map/index.js b/example/src/examples/Map/index.js
index 2efafc53f..bb89c7d92 100644
--- a/example/src/examples/Map/index.js
+++ b/example/src/examples/Map/index.js
@@ -6,6 +6,7 @@ export { default as PointInMapView } from './PointInMapView';
 export { default as ShowAndHideLayer } from './ShowAndHideLayer';
 export { default as ShowClick } from './ShowClick';
 export { default as ShowMap } from './ShowMap';
+export { default as MapUnMount } from './MapUnMount';
 export { default as ShowMapLocalStyle } from './ShowMapLocalStyle';
 export { default as ShowRegionDidChange } from './ShowRegionDidChange';
 export { default as SourceLayerVisibility } from './SourceLayerVisibility';
diff --git a/ios/RNMBX/RNMBXMapView.swift b/ios/RNMBX/RNMBXMapView.swift
index 34248c843..5aa9db7d4 100644
--- a/ios/RNMBX/RNMBXMapView.swift
+++ b/ios/RNMBX/RNMBXMapView.swift
@@ -154,7 +154,23 @@ class RNMBXCameraChanged : RNMBXEvent, RCTEvent {
 }
 
 @objc(RNMBXMapView)
-open class RNMBXMapView: UIView {
+open class RNMBXMapView: UIView, RCTInvalidating {
+  
+  public func invalidate() {
+    self.removeAllFeaturesFromMap(reason: .ViewRemoval)
+
+#if RNMBX_11
+    cancelables.forEach { $0.cancel() }
+    cancelables.removeAll()
+#endif
+    
+    _mapView.gestures.delegate = nil
+    _mapView.removeFromSuperview()
+    _mapView = nil
+    
+    self.removeFromSuperview()
+  }
+  
   var imageManager: ImageManager = ImageManager()
 
   var tapDelegate: IgnoreRNMBXMakerViewGestureDelegate? = nil