patterntypescriptreact-nativeModerate
Gesture Handling with react-native-gesture-handler
Viewed 0 times
react-native-gesture-handler v2
gesture handlerpan gestureswipeGestureDetectorUI threadtouchdrag
Problem
The built-in
PanResponder and TouchableHighlight APIs have latency and conflicts with scroll views. Complex gestures (swipe-to-dismiss, pinch-to-zoom) are difficult to implement reliably.Solution
Use
react-native-gesture-handler with the GestureDetector API (v2). Wrap the root of your app in GestureHandlerRootView. Compose gestures with Gesture.Simultaneous(), Gesture.Exclusive(), or Gesture.Race().Why
gesture-handler processes gestures on the UI thread (native side), not the JS thread. This eliminates the 1-2 frame lag introduced by passing touch events through the bridge. It also integrates with Reanimated for zero-JS-thread animations.
Gotchas
- Forgetting
GestureHandlerRootViewat the app root causes gestures to silently fail - On Android,
GestureHandlerRootViewmust wrap the entire app, not just a screen - Long-press gestures need
minDurationconfigured; the default may feel sluggish - Gesture conflicts between a Pan and a parent ScrollView require
simultaneousWithExternalGesture
Code Snippets
Draggable card with pan gesture and spring snap-back
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
import Animated, { useSharedValue, useAnimatedStyle } from 'react-native-reanimated';
export function DraggableCard() {
const x = useSharedValue(0);
const y = useSharedValue(0);
const pan = Gesture.Pan()
.onUpdate((e) => {
x.value = e.translationX;
y.value = e.translationY;
})
.onEnd(() => {
x.value = withSpring(0);
y.value = withSpring(0);
});
const style = useAnimatedStyle(() => ({
transform: [{ translateX: x.value }, { translateY: y.value }],
}));
return (
<GestureDetector gesture={pan}>
<Animated.View style={[styles.card, style]} />
</GestureDetector>
);
}Revisions (0)
No revisions yet.