How to Build Smooth and Responsive Swipeable Components with React Native Gesture Handler?

When we are making a good product on any digital platform at that time, we have to provide some different features and functionalities which can make our product more productive and look more efficient compared to other products. So providing swipe and gesture features in the app will make our app more user-friendly. So users can easily attract and perform an interaction with our app.

In this article, I will explain how we can create a swipeable component in react native.

There are many libraries and SDKs which provide swipe and gesture components and facilities.

➡️ We will use react-native-gesture-handler because it’s the most used and popular library. It Provides platform-specific touches and gestures for React native platform. You can install using the below command :

yarn add react-native-gesture-handler
cd ios && pod install

➡️ We have to wrap our whole app with GestureHandlerRootView so we can use the library’s gesture and swipe actions and methods.

➡️ Now we will move to make a swipeable component using react-native-gesture-handler’s Swipeable component.

The Swipable component allows you to create horizontal actions through which you can swipe left and right.

So In this demo, we will make a list and in that, we can create left and right swipeable actions.

➡️ So first we need to import the Swipeable component from the react-native-gesture-handler library given below:

import Swipeable from 'react-native-gesture-handler/Swipeable';

The Swipeable component has many properties as given here. But here for making a demo, we will use some basic required properties only like –

  • overshootLeft
  • overshootRight
  • renderRightActions
  • renderLeftActions

When we want to provide swipeable actions on the right side of a component so the user can swipe right to left and execute an action, the renderRightActions method can be useful.

The renderLeftActions function can be used to accomplish the same type of action. The swipeable panel can be dragged beyond the width of the right action panel if the overshootRight prop is given a boolean value. We can do the same for overshootLeft.

👉 overshootLeft

So we can write code for swipeable like given below:

return (
<Swipeable
overshootRight={false}
overshootLeft={false}
renderRightActions={(progress, dragX) =>
renderRightActions(progress, dragX, onPressDelete)
}
renderLeftActions={(progress, dragX) =>
renderLeftActions(progress, dragX, onMarkRead)
}
containerStyle={styles.swipableItemMainView}>
<View style={styles.itemWrap}>
<Text style={styles.title}>{notification?.title}</Text>
<Text style={styles.createdAt}>{notification?.createdAt}</Text>
</View>
</Swipeable>
);

While rendering left and right actions we have to use animated components so it looks more creative. You can write similar functions to render actions like those given below.

👉 renderRightActions

const renderRightActions = (progress, dragX, onPressDelete) => {
const scale = dragX.interpolate({
inputRange: [-100, -50, 0],
outputRange: [2, 1, 0],
extrapolate: 'clamp',
});
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => onPressDelete(index, notification)}
style={styles.rightAction}>
<Animated.Image
color={'white'}
source={deleteIcon2}
style={[{transform: [{scale}]}]}
/>
</TouchableOpacity>
);
};

👉 renderLeftActions

const renderLeftActions = (progress, dragX, onMarkRead) => {
const trans = dragX.interpolate({
inputRange: [0, 50, 100, 101],
outputRange: [-20, 0, 0, 1],
});
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => onMarkRead(index, notification)}
style={styles.leftAction}>
<Animated.Image
color={'white'}
source={markReadIcon}
style={[{transform: [{translateX: trans}]}]}
/>
</TouchableOpacity>
);
};

So now to make a proper demo we will use a sample list and use this Swipeable component. So our app App.js will look like the given below:

import {Alert, FlatList, StyleSheet, View} from 'react-native';
import React, {useState} from 'react';
import SwipableItem from './src/components/SwipableItem';
import {GestureHandlerRootView} from 'react-native-gesture-handler';

const App = () => {
const [list, setList] = useState([
{
title: 'This is the test notification',
createdAt: '23 March 2023',
},
{
title: 'This is the test notification',
createdAt: '22 March 2023',
},
{
title: 'This is the test notification',
createdAt: '21 March 2023',
},
{
title: 'This is the test notification',
createdAt: '20 March 2023',
},
{
title: 'This is the test notification',
createdAt: '19 March 2023',
},
]);

const renderListItem = ({item, index}) => {
return (
<SwipableItem
notification={item}
index={index}
onPressDelete={(index, notification) => {
Alert.alert(
'Test App',
'Are you sure you want to delete this notification?',
[
{
text: 'No',
onPress: () => null,
},
{
text: 'Yes',
onPress: () => {
let sampleList = list;
sampleList = sampleList.filter((obj, i) => i != index);
setList(sampleList);
},
},
],
);
}}
onMarkRead={(index, notification) => {
console.log('onMarkRead index, notification', index, notification);
}}
/>
);
};

return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.container}>
<FlatList
data={list}
renderItem={renderListItem}
contentContainerStyle={{flexGrow: 1, backgroundColor: 'white'}}
/>
</View>
</GestureHandlerRootView>
);
};

export default App;

const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 50,
backgroundColor: 'white',
},
});

So here we have wrapped our main app with GestureHandlerRootView to get all the library’s features with native touch and gestures. So we are considering a notification list and we want to delete a single notification using the swipe actions like the Gmail app.

Our final Swipeable component code will look like the given below:

import {Animated, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import React from 'react';
import Swipeable from 'react-native-gesture-handler/Swipeable';

const deleteIcon2 = require('../images/deleteIcon1.png');
const markReadIcon = require('../images/markReadIcon.png');

const SwipableItem = ({notification, onPressDelete, index, onMarkRead}) => {
const renderRightActions = (progress, dragX, onPressDelete) => {
const scale = dragX.interpolate({
inputRange: [-100, -50, 0],
outputRange: [2, 1, 0],
extrapolate: 'clamp',
});
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => onPressDelete(index, notification)}
style={styles.rightAction}>
<Animated.Image
color={'white'}
source={deleteIcon2}
style={[{transform: [{scale}]}]}
/>
</TouchableOpacity>
);
};

const renderLeftActions = (progress, dragX, onMarkRead) => {
const trans = dragX.interpolate({
inputRange: [0, 50, 100, 101],
outputRange: [-20, 0, 0, 1],
});
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => onMarkRead(index, notification)}
style={styles.leftAction}>
<Animated.Image
color={'white'}
source={markReadIcon}
style={[{transform: [{translateX: trans}]}]}
/>
</TouchableOpacity>
);
};

return (
<Swipeable
overshootRight={false}
overshootLeft={false}
renderRightActions={(progress, dragX) =>
renderRightActions(progress, dragX, onPressDelete)
}
renderLeftActions={(progress, dragX) =>
renderLeftActions(progress, dragX, onMarkRead)
}
containerStyle={styles.swipableItemMainView}>
<View style={styles.itemWrap}>
<Text style={styles.title}>{notification?.title}</Text>
<Text style={styles.createdAt}>{notification?.createdAt}</Text>
</View>
</Swipeable>
);
};

export default SwipableItem;

const styles = StyleSheet.create({
title: {
fontSize: 14,
color: 'black',
fontWeight: '700',
},
createdAt: {
fontSize: 12,
color: 'gray',
fontWeight: '500',
marginTop: 7,
},
rightAction: {
flex: 0.2,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'red',
},
leftAction: {
flex: 0.2,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'lightblue',
},
itemWrap: {
backgroundColor: 'pink',
paddingVertical: 15,
paddingHorizontal: 10,
flex: 1,
},
swipableItemMainView: {
marginVertical: 10,
marginHorizontal: 10,
},
childrenContainerStyle: {
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'white',
},
});

We can see in the given screenshot what we achieved using the Swipeable component.

Please click here to watch the demo video.

coma

Conclusion

In this blog, I have covered the fundamental aspects of swipeable components, which can add a variety of functionalities to our app. These components come with numerous props and methods, enabling us to unlock a wide range of features.

By incorporating swipe and gesturing capabilities, we can attract diverse user groups and create a distinct experience with our product.

Let’s embrace the joy of coding and continue to create innovative solutions!😇

Ronak K

React-Native Developer

Ronak is a React-Native developer with more than 4 years of experience in developing mobile applications for Android and iOS. He is dedicated to his work and passion. He worked in different kinds of application industries that have responsive designs. He also has knowledge of how to make an app with expo cli and react-native web and some basic understanding of react.js.

Keep Reading

Keep Reading

Mindbowser is excited to meet healthcare industry leaders and experts from across the globe. Join us from Feb 25th to 28th, 2024, at ViVE 2024 Los Angeles.

Learn More

Let's create something together!