React Native Swipe Gestures
react-native-swipe-gestures is a React Native component designed to detect and handle 4-directional swipe gestures: up, down, left, and right. It provides a `GestureRecognizer` component that wraps other UI elements, enabling them to respond to these directional swipe events. The library allows for fine-grained control over gesture sensitivity through configurable parameters such as `velocityThreshold`, `directionalOffsetThreshold`, and `gestureIsClickThreshold`. Currently at version 1.0.5, this package offers a straightforward, declarative API for implementing common swipe interactions, abstracting the complexities of React Native's underlying `PanResponder`. It also ships with TypeScript type definitions, providing an improved development experience for TypeScript users. While effective for basic swipe detection, for more complex gesture interactions or higher performance requirements (e.g., gestures running on the UI thread), alternative libraries like `react-native-gesture-handler` (v2.0+) might be considered.
Common errors
-
TypeError: Cannot read property 'default' of undefined
cause Attempting to `require` the module and directly destructure `GestureRecognizer` when it's a default export, or attempting to use `.default` on a named export.fixIf using CommonJS, `GestureRecognizer` is the default export: `const GestureRecognizer = require('react-native-swipe-gestures').default;`. Named exports like `swipeDirections` are accessed as `const { swipeDirections } = require('react-native-swipe-gestures');`. -
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
cause This typically occurs when `GestureRecognizer` is imported incorrectly, resulting in `undefined` being passed as a component to React's renderer.fixEnsure the import statement for `GestureRecognizer` is correct: `import GestureRecognizer from 'react-native-swipe-gestures';`. If using CommonJS, use `const GestureRecognizer = require('react-native-swipe-gestures').default;`. -
Swipe gestures not detected even when component is rendered.
cause The `GestureRecognizer` component might not have sufficient size or `flex` properties to register touch events across its intended area.fixVerify that `GestureRecognizer` or its containing `View` has a defined width, height, or `flex` property (e.g., `style={{flex: 1}}`) so it can capture touch interactions.
Warnings
- gotcha The package's latest version (1.0.5) was published over six years ago (March 2020), indicating it may not be actively maintained or updated for newer React Native versions or architectures (e.g., Fabric). Users might encounter compatibility issues with recent React Native releases or performance limitations inherent to gesture handling on the JavaScript thread.
- gotcha Incorrect styling of the `GestureRecognizer` component (e.g., missing `flex: 1` or explicit width/height) can prevent it from properly registering touch events, as it relies on its rendered area to detect gestures. If the component has no dimensions, it cannot receive touches.
- gotcha The `gestureState` object passed to swipe callbacks provides raw information from React Native's `PanResponder`. Developers unfamiliar with its structure might misuse properties or misinterpret gesture data, leading to incorrect swipe logic.
- gotcha This library might conflict with other gesture detection systems in a parent or sibling component (e.g., an outer `ScrollView` or another `PanResponder`). This can lead to gestures being consumed by the wrong handler or not firing at all.
Install
-
npm install react-native-swipe-gestures -
yarn add react-native-swipe-gestures -
pnpm add react-native-swipe-gestures
Imports
- GestureRecognizer
import { GestureRecognizer } from 'react-native-swipe-gestures';import GestureRecognizer from 'react-native-swipe-gestures';
- swipeDirections
import swipeDirections from 'react-native-swipe-gestures';
import { swipeDirections } from 'react-native-swipe-gestures'; - All symbols (CommonJS)
const { GestureRecognizer, swipeDirections } = require('react-native-swipe-gestures');const GestureRecognizer = require('react-native-swipe-gestures').default; const { swipeDirections } = require('react-native-swipe-gestures');
Quickstart
import React, { Component, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import GestureRecognizer, { swipeDirections } from 'react-native-swipe-gestures';
const App = () => {
const [myText, setMyText] = useState('I\'m ready to get swiped!');
const [gestureName, setGestureName] = useState('none');
const [backgroundColor, setBackgroundColor] = useState('#fff');
const onSwipeUp = () => setMyText('You swiped up!');
const onSwipeDown = () => setMyText('You swiped down!');
const onSwipeLeft = () => setMyText('You swiped left!');
const onSwipeRight = () => setMyText('You swiped right!');
const onSwipe = (direction) => {
const { SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT } = swipeDirections;
setGestureName(direction);
switch (direction) {
case SWIPE_UP: setBackgroundColor('red'); break;
case SWIPE_DOWN: setBackgroundColor('green'); break;
case SWIPE_LEFT: setBackgroundColor('blue'); break;
case SWIPE_RIGHT: setBackgroundColor('yellow'); break;
default: setBackgroundColor('#fff'); break;
}
};
const config = {
velocityThreshold: 0.3,
directionalOffsetThreshold: 80,
gestureIsClickThreshold: 5
};
return (
<View style={styles.container}>
<GestureRecognizer
onSwipe={(direction, state) => onSwipe(direction, state)}
onSwipeUp={(state) => onSwipeUp(state)}
onSwipeDown={(state) => onSwipeDown(state)}
onSwipeLeft={(state) => onSwipeLeft(state)}
onSwipeRight={(state) => onSwipeRight(state)}
config={config}
style={[styles.gestureArea, { backgroundColor: backgroundColor }]}
>
<Text style={styles.text}>{myText}</Text>
<Text style={styles.text}>onSwipe callback received: {gestureName}</Text>
</GestureRecognizer>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
gestureArea: {
flex: 1,
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 20,
color: 'black',
marginBottom: 10,
},
});
export default App;