Gesture handling in React Native with react-native-gesture-handler

Touch and gesture interactions are the core of great mobile UX. If your gestures feel laggy or inconsistent, users will feel it immediately. In this guide, you will learn how to implement smooth, native-feel gestures with react-native-gesture-handler using modern APIs, plus the setup steps that avoid the most common pitfalls.
If you want to start from a production-ready foundation, explore our React Native templates and ship your next app faster.
Ship faster with All Access. Get the React Native templates, admin panels, updates, and launch bonuses that help you build faster.
Explore All AccessInstallation
Expo
expo install react-native-gesture-handler
React Native CLI
yarn add react-native-gesture-handler
Then ensure your entry file (e.g., index.js) imports the library before any other imports:
import "react-native-gesture-handler";
Finally, wrap your app in GestureHandlerRootView:
import React from "react";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import App from "./App";
export default function Root() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<App />
</GestureHandlerRootView>
);
}
If you plan to animate gestures smoothly, install Reanimated as well:
yarn add react-native-reanimated
The modern gesture API (recommended)
The new Gesture API works great with Reanimated and keeps animations on the UI thread for smooth performance.
Tap gesture (press effect)
import React from "react";
import { View, Text } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";
export default function TapCard() {
const scale = useSharedValue(1);
const tap = Gesture.Tap()
.onBegin(() => {
scale.value = 0.96;
})
.onFinalize(() => {
scale.value = withSpring(1);
});
const style = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
return (
<GestureDetector gesture={tap}>
<Animated.View style={[{ padding: 16, backgroundColor: "#111", borderRadius: 12 }, style]}>
<Text style={{ color: "#fff" }}>Tap me</Text>
</Animated.View>
</GestureDetector>
);
}
Pan gesture (drag a card)
import React from "react";
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
export default function DraggableCard() {
const x = useSharedValue(0);
const y = useSharedValue(0);
const pan = Gesture.Pan()
.onChange((e) => {
x.value += e.changeX;
y.value += e.changeY;
})
.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={[{ width: 160, height: 120, backgroundColor: "#0f172a", borderRadius: 16 }, style]} />
</GestureDetector>
);
}
Working with ScrollView and nested gestures
When gestures compete (e.g., a card inside a ScrollView), use simultaneousWithExternalGesture or requireExternalGestureToFail to control priority:
const scroll = Gesture.Native();
const pan = Gesture.Pan().simultaneousWithExternalGesture(scroll);
This keeps your drag interactions smooth without blocking the main scroll.
Performance tips
- Keep logic inside gesture callbacks light. Heavy work should be offloaded or deferred.
- Prefer Reanimated values (
useSharedValue) for animation-driven interactions. - Only use
runOnJSwhen you must update React state.
Ship faster with All Access. Get the React Native templates, admin panels, updates, and launch bonuses that help you build faster.
Explore All AccessTroubleshooting
"GestureHandlerRootView is not found"
Make sure your app is wrapped with GestureHandlerRootView and that the library import is at the top of your entry file.
Gestures feel laggy
Check that you are using the new Gesture API with Reanimated, not JS-based animated values.
Touch conflicts in lists
Use simultaneousWithExternalGesture or require the scroll gesture to fail before your pan begins.
Looking for a custom mobile application?
Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.
Get in TouchConclusion
The best mobile apps feel effortless because their gestures are smooth, native, and predictable. With react-native-gesture-handler, you can build interactions that feel at home on both iOS and Android.
If you want to ship faster, start from a production-ready codebase with our React Native templates.
Explore related templates
- React Native Social Network
- React Native Dating App
- Food Delivery App
- Short-Video (TikTok) Clone
- AI Chat App (ChatGPT template)
Or get everything at once with the All Access pass: All Access - Mega Bundle