iOS: Static MapView with PROVIDER_GOOGLE silently blocks gestures on a second interactive MapView
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 66/100
- Issue type
- Documentation
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- ios, react-native
- Domain
- documentation, mobile
Research direction
Start with the README and the existing PROVIDER_GOOGLE documentation. Add a warning about multiple Google MapView instances on iOS interfering with gestures, and document the Apple Maps plus cacheEnabled workaround for static previews. Check the rendered documentation to confirm the warning and recommendation are clear.
Written by the indexing model from the issue text.
Description
Environment
react-native-maps: 1.27.2- React Native: 0.83
- Expo SDK: 55 (New Architecture / Fabric)
- iOS: 17+ (tested on simulator iOS 26 and real device via TestFlight)
- Provider:
PROVIDER_GOOGLEon both instances
Summary
When two MapView instances with PROVIDER_GOOGLE coexist in the same view hierarchy on iOS -- a non-interactive "preview" one (scrollEnabled={false}, zoomEnabled={false}, rotateEnabled={false}, pitchEnabled={false}, pointerEvents="none") and an interactive fullscreen one inside a Modal -- all gestures (pan / zoom / tap) on the interactive one are silently blocked. onMapReady fires, tiles render, onRegionChangeComplete fires once for the initial region, but no subsequent onRegionChange, onPanDrag, or onPress events are emitted. This persists across Modal re-opens until the app is restarted.
Reproduction
Minimal repro is straightforward:
- Render a screen that contains a
<MapView provider={PROVIDER_GOOGLE} scrollEnabled={false} zoomEnabled={false} ... />as a static preview. - On tap, open a Modal containing an interactive
<MapView provider={PROVIDER_GOOGLE} />. - Try to pan/zoom/tap the interactive map. Nothing happens.
- Remove the static preview from the screen entirely -> the interactive map works normally.
Root cause
Confirmed by Xcode View Hierarchy Debugger: both GMSMapView instances register native UIGestureRecognizer objects. Disabling gestures via scrollEnabled={false} etc. does not remove the recognizers, it only flips their enabled state. They remain in the hit-testing chain, where they interfere with the recognizers of the second GMSMapView.
This is consistent with Google's own statement: "Maps SDK for iOS has not been optimized for multiple windows/instances and may result in undefined behavior." -- https://developers.google.com/maps/documentation/ios-sdk/start
Workaround (what actually works)
Use Apple Maps (default provider, provider={undefined}) for the non-interactive preview on iOS, with cacheEnabled={true} so it renders as a cached image. Keep PROVIDER_GOOGLE for the interactive fullscreen map. This works because Apple Maps (MKMapView) and Google Maps (GMSMapView) use entirely separate gesture stacks.
// iOS: Apple Maps + cacheEnabled (static image, no gesture recognizers)
// Android: Google Maps + liteMode (bitmap)
<MapView
provider={Platform.OS === 'ios' ? undefined : PROVIDER_GOOGLE}
scrollEnabled={false}
zoomEnabled={false}
rotateEnabled={false}
pitchEnabled={false}
liteMode={Platform.OS === 'android'}
cacheEnabled={Platform.OS === 'ios'}
pointerEvents="none"
/>
What I think the library could do
Three possible directions, in rough order of preference:
-
Documentation warning. Add an explicit note in the README /
PROVIDER_GOOGLEdocs that twoPROVIDER_GOOGLEinstances in the same view hierarchy on iOS can break gestures, and recommend Apple Maps +cacheEnabled(orliteModeon Android) for static previews. This is the cheapest fix and immediately saves people days of debugging. -
iOS equivalent of
liteMode. Implement iOSliteModeviaMKMapSnapshotter(Apple Maps) or viaGMSMapView.takeSnapshot+ replace-with-image lifecycle (Google Maps). Discussed in #2497 and #1411 but never shipped. A concrete modern use case: mobile apps that show a small map preview on a list/detail screen and open a fullscreen interactive map on tap. WithoutliteModeon iOS, this pattern silently breaks. -
Explicit API to detach gesture recognizers. A prop like
gestureRecognizersEnabled={false}that calls-[UIView removeGestureRecognizer:]on all recognizers of the underlyingGMSMapView, not just flips theirenabledflag. This would be more targeted thanliteModefor users who want a live (not cached) static map without gesture interference.
Additional notes
- This is not a regression in
react-native-maps-- it's a Google SDK limitation. But the library is where developers hit it, and documenting the workaround here would be high-leverage. - The symptom is particularly confusing because the broken map still renders tiles and fires
onMapReady. Developers naturally look for overlays,pointerEvents, Modal issues, etc. before suspecting a secondMapViewinstance elsewhere on the screen. - Issue #2497 ("Feature: liteMode support on iOS via MKMapSnapshotter") was closed 7+ years ago without resolution. Filing this fresh with a concrete repro and confirmed workaround seems more useful than commenting on a stale thread.
Happy to provide a minimal repro repo if helpful.
- Dominant language
- TypeScript
- Stars
- 16k
- Forks
- 5k
- Avg merge
- 9d 9h
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from react-native-maps/react-native-maps
-
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
react-native-maps/react-native-maps#5987 · 1 comment ·
All issues in react-native-maps/react-native-maps
Similar issues
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
dennys-bd/agent-hive#184 ·
-
Add: hunch Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AbdelStark/awesome-typesafe#104 ·
-
ai-observability bug team/ai-observability
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
vicharanashala/fln#563 ·