React Native

React Native "Gestures Not Working" Inside ScrollView or Modal

· by DebuggedIt

Quick answer

Gestures that work fine on a normal screen but stop responding specifically inside a ScrollView or Modal almost always come down to gesture recognition...

Gestures that work fine on a normal screen but stop responding specifically inside a ScrollView or Modal almost always come down to gesture recognition conflicts — the scroll gesture and your custom gesture are both competing for the same touch events, and without explicit configuration, one wins in a way that blocks the other.

The Problem

A tappable component, swipeable item, or custom gesture handler works correctly when placed directly on a screen, but becomes unresponsive — taps don't register, swipes don't trigger — once nested inside a ScrollView or rendered within a Modal.

Why It Happens

Several distinct but related causes commonly produce this exact symptom:

  • ScrollView itself is a gesture recognizer (for scrolling), and by default, React Native's touch system can have ambiguity about whether a touch should be interpreted as a scroll gesture or as a tap/gesture on a child component, especially with libraries like react-native-gesture-handler that have their own gesture resolution system separate from the basic React Native touch responder system
  • A Modal renders its content in a separate native view hierarchy (particularly on iOS), which can interact unexpectedly with gesture handler libraries that weren't specifically designed with this separate rendering context in mind, particularly for older library versions
  • Missing or incorrect simultaneousHandlers configuration when using react-native-gesture-handler, which by default assumes gestures should be mutually exclusive unless explicitly told they can be recognized simultaneously alongside a scroll gesture
  • A z-index or pointer-events configuration issue where an overlapping component (often part of the Modal's own backdrop or an absolutely positioned sibling) is intercepting touches before they reach the intended gesture target underneath it

The Fix

If you're using react-native-gesture-handler, wrap your gesture-enabled component with explicit configuration allowing it to work simultaneously with the surrounding ScrollView's own scroll gesture, rather than assuming they'll automatically coexist:

import { PanGestureHandler } from 'react-native-gesture-handler';

const scrollRef = useRef(null);
const panRef = useRef(null);

<ScrollView ref={scrollRef}>
  <PanGestureHandler
    ref={panRef}
    simultaneousHandlers={scrollRef}
    onGestureEvent={handleGesture}
  >
    <Animated.View>{/* your gesture-enabled content */}</Animated.View>
  </PanGestureHandler>
</ScrollView>

simultaneousHandlers explicitly tells the gesture system that both the pan gesture and the scroll view's own scroll gesture are allowed to be recognized at the same time, rather than the default behavior of one blocking the other entirely.

Ensure your app's root component is properly wrapped with GestureHandlerRootView, which is required for react-native-gesture-handler to function correctly at all, and its absence can produce exactly this kind of "gestures silently don't work" symptom without any clear error message pointing at the missing wrapper:

import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* rest of your app */}
    </GestureHandlerRootView>
  );
}

For gestures specifically inside a Modal, confirm you're using a Modal implementation that properly supports gesture handler libraries — some Modal implementations, especially custom or older ones, don't correctly bridge the native gesture recognition context the same way the main app view does. If you're using React Navigation's own modal presentation rather than React Native's built-in Modal component, this is often more reliable for gesture compatibility, since it's designed to work within the same navigation and gesture context as the rest of your app rather than a separate native modal presentation.

Check for overlapping components intercepting touches, particularly with absolutely positioned elements or a Modal's own backdrop, using pointerEvents to explicitly allow touches to pass through elements that shouldn't be intercepting them:

<View style={styles.overlay} pointerEvents="box-none">
  {/* This container itself won't intercept touches meant for children,
      but children can still receive their own touches normally */}
  <YourGestureComponent />
</View>

Still Not Working?

If gestures work correctly on Android but fail specifically on iOS (or vice versa), which is a common pattern with gesture handling inside Modals specifically, check for known platform-specific issues with your exact combination of React Native, gesture handler, and modal library versions — gesture handling inside modals has historically had platform-specific edge cases that get fixed incrementally across library versions, and checking the specific library's GitHub issues for your exact version combination and platform often surfaces either a known workaround or confirmation that upgrading to a newer library version resolves the specific inconsistency you're encountering.