One of the more frustrating debugging experiences in Rork app development is when swipes and taps simply stop working — and nothing shows up in the console. No error, no warning, just silence.
This typically comes down to React Native Gesture Handler configuration issues or component layering conflicts. Rork's AI generates accurate functional logic, but the touch event layer is one area that often requires manual verification. Gesture problems are also notoriously hard to reproduce consistently across devices, which is why having a systematic checklist matters.
Here are the five most common culprits, each with a concrete fix.
Cause #1: GestureHandlerRootView Is Missing
Since Expo SDK 50, wrapping your app's root in GestureHandlerRootView is required whenever you use react-native-gesture-handler. Rork sometimes omits this wrapper — particularly when generating screens with swipeable cards, draggable list items, or bottom sheet components.
// ❌ Common issue: root is not wrapped
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import RootNavigator from './navigation/RootNavigator';
export default function App() {
return (
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
);
}
// ✅ Fixed: wrap with GestureHandlerRootView
import React from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { NavigationContainer } from '@react-navigation/native';
import RootNavigator from './navigation/RootNavigator';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
</GestureHandlerRootView>
);
}Don't omit style={{ flex: 1 }} — leaving it out causes the layout to collapse to zero height. Adding this single wrapper often brings all swipe-based gestures back to life instantly.
Where to find this file in a Rork project: Look for App.tsx or app/_layout.tsx if you're using Expo Router. The GestureHandlerRootView should wrap everything, sitting just inside or just outside your navigation root.
Cause #2: An Invisible View Is Stealing Touches
When you layer components using zIndex or position: 'absolute', an invisible View sitting on top can intercept all touch events before they reach your buttons or swipeable elements. This is especially common with modals, overlays, and decorative gradient backgrounds generated by Rork.
// ❌ Problem: transparent full-screen View is consuming all touches
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
{/* gradient or background decoration */}
</View>
<TouchableOpacity onPress={handlePress}>
<Text>Nothing happens when you press this</Text>
</TouchableOpacity>
// ✅ Fix: set pointerEvents="none" to let touches pass through
<View
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
pointerEvents="none"
>
{/* visual-only — touch events pass through to components below */}
</View>
<TouchableOpacity onPress={handlePress}>
<Text>Responds correctly now</Text>
</TouchableOpacity>Quick diagnosis method: Temporarily set suspected components to display: 'none' and check if gestures start working. If they do, you've found the culprit. Add pointerEvents="none" and restore the component. This trial-and-error approach works faster than reading through nested JSX trying to spot z-index issues.
Cause #3: ScrollView and Swipe Gesture Are Competing
Placing swipe cards or horizontal sliders inside a vertical ScrollView creates ambiguity — React Native can't decide whether you want to scroll vertically or swipe horizontally, so it often does neither cleanly.
// ✅ iOS-only option: directionalLockEnabled commits to one axis
<ScrollView directionalLockEnabled={true}>
<SwipeableCard />
</ScrollView>
// ✅ More reliable: use PanGesture with explicit direction thresholds
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
export function SwipeCard() {
const translateX = useSharedValue(0);
const swipeGesture = Gesture.Pan()
.activeOffsetX([-10, 10]) // activate after 10px horizontal movement
.failOffsetY([-5, 5]) // yield to scroll after 5px vertical movement
.onUpdate((event) => {
translateX.value = event.translationX;
})
.onEnd((event) => {
// snap back if swipe distance is small, otherwise dismiss
if (Math.abs(event.translationX) < 80) {
translateX.value = withSpring(0);
} else {
translateX.value = withSpring(event.translationX > 0 ? 400 : -400);
}
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
}));
return (
<GestureDetector gesture={swipeGesture}>
<Animated.View style={[styles.card, animatedStyle]}>
{/* card content */}
</Animated.View>
</GestureDetector>
);
}The activeOffsetX / failOffsetY combination is what makes this work. With these thresholds in place, the gesture handler and the scroll container negotiate cleanly — horizontal movement triggers the swipe, vertical movement hands off to the scroll view. This pattern is reliable across both iOS and Android without any platform-specific workarounds.
For a deeper dive into gesture-based animations in Rork, see Swipe Animations with Reanimated and Gesture Handler: A Complete Guide.
Cause #4: Android Touch Delay Makes It Feel Broken
On Android, the ripple effect from TouchableNativeFeedback and Pressable can make taps feel sluggish — especially on mid-range devices. This isn't a bug, but when combined with swipe card UIs or fast interaction sequences, it's easily mistaken for a gesture failure.
// ✅ Minimize perceived touch delay with Pressable
<Pressable
onPress={handlePress}
android_ripple={{ color: 'rgba(0,0,0,0.08)' }}
unstable_pressDelay={0} // register press immediately on touch down
style={({ pressed }) => [
styles.card,
{ opacity: pressed ? 0.85 : 1 },
]}
>
<Text>Feels responsive now</Text>
</Pressable>unstable_pressDelay={0} has an alarming name but works reliably in production. The "unstable" label means the API surface may change in a future React Native version — check when upgrading.
For small icon buttons that are technically tappable but feel inaccurate, expand the touch area with hitSlop:
<Pressable
onPress={handlePress}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
style={styles.iconButton}
>
{/* icon */}
</Pressable>A good rule of thumb: any tap target smaller than 44×44 points should have hitSlop added. Apple's Human Interface Guidelines and Google's Material Design both recommend this minimum touch target size.
Cause #5: Gestures Don't Work Inside a Modal
React Native's Modal component renders in a separate native window, outside the scope of the GestureHandlerRootView you placed at the app root. Any gesture-based components inside a Modal silently fail unless you add a second wrapper inside the Modal itself.
// ❌ Swipes inside Modal are silently ignored
import { Modal } from 'react-native';
<Modal visible={isVisible} transparent animationType="slide">
<SwipeableBottomSheet /> {/* gestures don't register */}
</Modal>
// ✅ Add GestureHandlerRootView inside the Modal
import { Modal } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
<Modal visible={isVisible} transparent animationType="slide">
<GestureHandlerRootView style={{ flex: 1 }}>
<SwipeableBottomSheet /> {/* now works correctly */}
</GestureHandlerRootView>
</Modal>This pattern comes up most often with custom bottom sheet implementations. If you're using @gorhom/bottom-sheet, check its documentation for Modal-specific setup — well-maintained libraries typically have dedicated guidance for this scenario.
Still Not Working? A Diagnostic Checklist
If none of the five causes above resolves your issue, work through these systematically:
- Check that
react-native-gesture-handlerandreact-native-reanimatedversions are compatible — mismatched versions cause silent failures. Cross-reference with Expo's compatibility table for your SDK version. - Test on a production EAS Build, not Expo Go. Gesture Handler behavior can differ meaningfully between the two environments.
- If iOS and Android behave differently, you likely need platform-specific handling with
Platform.OSchecks. - Look for any parent component with
overflow: 'hidden', which can clip touch areas on Android. - Verify that no component in the tree has
pointerEvents="none"applied unintentionally — Rork occasionally generates this to prevent interaction during loading states and forgets to remove it.
When asking Rork to fix gesture issues, be specific in your prompt. Mention that you've already confirmed GestureHandlerRootView is in place, describe which gesture type isn't working (tap, swipe, long press), and which screen it happens on. A targeted hypothesis leads to a much more useful response than a vague description.
For more on building resilient Rork apps, Error Handling and Crash Prevention Basics covers the patterns that help you catch problems before users do.