React Native Gesture Handler
React Native Gesture Handler is a declarative API that exposes the native platform's touch and gesture system to React Native applications. It provides a robust and performant way to handle complex gestures like pan, pinch, rotate, and tap directly on the native UI thread, leading to smoother animations and a more responsive user experience compared to JavaScript-based gesture systems. The current stable version is 2.31.1, with an active release cadence that frequently publishes patch and minor updates, and a significant version 3.0 in public beta. Key differentiators include its deep integration with the native UI, enabling seamless interoperability with `react-native-reanimated` for advanced animations, and its move towards a hook-based API in version 3 designed for React Native's New Architecture. It aims to reduce the load on the JavaScript thread by offloading gesture recognition to the native side.
Common errors
-
Invariant Violation: 'RNGestureHandlerModule' could not be found.
cause The native module for react-native-gesture-handler is not correctly linked or initialized, often due to improper installation, outdated linking for older React Native versions, or caching issues.fixRun `npx react-native link react-native-gesture-handler` (for older RN versions, though auto-linking is default now). Try clearing Metro cache (`npx react-native start --reset-cache`), clearing watchman watches (`watchman watch-del-all`), reinstalling node modules and pods (`rm -rf node_modules && yarn install && cd ios && pod install`). For Android, try `cd android && ./gradlew clean`. -
Gestures are not recognized or do not trigger any events.
cause The `GestureHandlerRootView` is missing, or the component handling the gesture is not correctly wrapped by a `GestureDetector` (v3) or an appropriate `GestureHandler` component (v2), or the gesture handler hierarchy is incorrect.fixEnsure your application's root component is wrapped with `GestureHandlerRootView`. If using v3, verify `GestureDetector` wraps the interactive component. If using v2, ensure `gestureHandlerRootHOC` is applied or the specific `GestureHandler` component (e.g., `PanGestureHandler`) is correctly positioned in the component tree. -
TypeScript error: Property 'SomeTouchableComponent' does not exist on type 'typeof import("react-native-gesture-handler")'cause Specific Touchable components (e.g., `TouchableNativeFeedback`, `TouchableOpacity`) from `react-native-gesture-handler` might have changed their export or type definition, or there's a version mismatch with React Native types.fixCheck the changelog for any changes to Touchable components. Ensure `react-native-gesture-handler` and its `@types/react-native` peer dependency are up to date. As of v2.31.1, fixes for Touchables TypeScript errors were applied, suggesting this was a known issue. -
Android build error: Duplicate class com.swmansion.gesturehandler.BuildConfig found in modules jetified-react-native-gesture-handler... and react-native-gesture-handler...
cause This usually indicates an issue with Android's dependency resolution, often due to mixing different versions or linking types of the library (e.g., direct and auto-linked), or a cached build issue.fixClean your Android project: `cd android && ./gradlew clean`. Ensure your `build.gradle` configuration isn't including `react-native-gesture-handler` multiple times or in conflicting ways. Rebuild the project. Sometimes deleting the `.gradle` folder in the project's root and in `android/.gradle` helps, followed by a full reinstall and `pod install` for iOS.
Warnings
- breaking Version 3.0 introduces a new hook-based API (`GestureDetector`, `Gesture`) and significant internal changes tailored for the New Architecture. Projects upgrading from v2.x will require substantial code refactoring, especially for gesture definitions.
- deprecated The `gestureHandlerRootHOC` higher-order component was deprecated in favor of wrapping your app with `GestureHandlerRootView` for better compatibility and New Architecture support.
- gotcha Gestures may not work correctly on Android or in applications using the New Architecture without wrapping the root component of your application with `GestureHandlerRootView`.
- gotcha Compatibility with React Native versions is critical. Upgrading `react-native-gesture-handler` without updating `react-native` (or vice-versa) to compatible versions can lead to build errors or runtime issues.
- breaking In v3.0.0-beta.3, the event object passed to `onDeactivate` and `onFinalize` handlers now includes the `end` flag directly within the event object, which might require adjusting event destructuring.
Install
-
npm install react-native-gesture-handler -
yarn add react-native-gesture-handler -
pnpm add react-native-gesture-handler
Imports
- GestureDetector
import GestureDetector from 'react-native-gesture-handler';
import { GestureDetector, Gesture } from 'react-native-gesture-handler'; - TapGestureHandler
const TapGestureHandler = require('react-native-gesture-handler').TapGestureHandler;import { TapGestureHandler, State } from 'react-native-gesture-handler'; - gestureHandlerRootHOC
import { gestureHandlerRootHOC } from 'react-native-gesture-handler'; - GestureHandlerRootView
import { GestureHandlerRootView } from './GestureHandlerRootView';import { GestureHandlerRootView } from 'react-native-gesture-handler';
Quickstart
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
function AppContent() {
const [count, setCount] = React.useState(0);
// Define a simple tap gesture
const tapGesture = Gesture.Tap()
.onEnd(() => {
// This runs on the UI thread for performance
setCount(prev => prev + 1);
})
.numberOfTaps(1); // Respond to single taps
return (
<View style={styles.container}>
<GestureDetector gesture={tapGesture}>
<View style={styles.box}>
<Text style={styles.text}>Tap Me!</Text>
<Text style={styles.text}>Taps: {count}</Text>
</View>
</GestureDetector>
</View>
);
}
// It is crucial to wrap your entire application with GestureHandlerRootView
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<AppContent />
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
box: {
width: 150,
height: 150,
backgroundColor: '#61dafb',
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
padding: 20
},
text: {
fontSize: 20,
color: 'white',
fontWeight: 'bold',
textAlign: 'center'
}
});