# How to Implement Swipe-to-Delete in React Native: A Step-by-Step Tutorial

> Originally written in 2024. Content may vary slightly across newer versions.

#### Introduction

Swipe-to-delete functionality enhances user interaction by allowing effortless removal of items from lists with a simple swipe gesture. In this tutorial, we’ll demonstrate how to achieve swipe-to-delete in React Native projects, **whether set up with React Native CLI or Expo!**

#### Step-by-Step Guide: React Native CLI Project

Initialize a new React Native project using the React Native CLI:

```shell
npx react-native init SwipeToDeleteRN
```

**Dependencies Installation:**

Install the required dependencies for swipe-to-delete:

```shell
npm install react-native-gesture-handler
```

For iOS users, navigate to the iOS directory and run:

```shell
pod install
```

In the `App.js`, wrap the app within a gesture handler root view and *ensure to apply* `flex: 1` *to the component:*

```javascript
import { GestureHandlerRootView } from "react-native-gesture-handler";  
  
const App = () => {  
  return (  
    <GestureHandlerRootView style={{ flex: 1 }}>  
      <MessagesScreen />  
    </GestureHandlerRootView>  
  );  
};  
  
export default App;
```

The above code snippets contain a messages screen to display a list of messages that can be swipe deleted.

Here is the breakdown for the `MessagesScreen` component:

```javascript
import { FlatList, StyleSheet } from 'react-native';
import React, { useState } from 'react';

import Screen from '../components/Screen';
import ListItem from '../components/ListItem';
import ListItemSeparator from '../components/ListItemSeparator';
import ListItemDeleteAction from '../components/ListItemDeleteAction';

const initialMessages = [
  {
    id: 1,
    title: 'title one',
    description: 'description one',
    image: require('../assets/cat.jpg'),
  },
  {
    id: 2,
    title: 'title two',
    description: 'description two',
    image: require('../assets/cat.jpg'),
  },
  {
    id: 3,
    title: 'title three',
    description: 'description three',
    image: require('../assets/cat.jpg'),
  },
];

export default function MessagesScreen() {
  const [messages, setMessages] = useState(initialMessages);
  const [refreshing, setRefreshing] = useState(false);
  const handleDelete = message => {
    setMessages(messages => messages.filter(item => item.id !== message.id));
  };
  return (
    <Screen>
      <FlatList
        data={messages}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <ListItem
            title={item.title}
            subTitle={item.description}
            image={item.image}
            onPress={() => console.log('item clicked.')}
            renderRightActions={() => (
              <ListItemDeleteAction onPress={() => handleDelete(item)} />
            )}
          />
        )}
        ItemSeparatorComponent={ListItemSeparator}
        refreshing={refreshing}
        onRefresh={() => {
          setMessages([
            {
              id: 1,
              title: 'title one',
              description: 'description one',
              image: require('../assets/cat.jpg'),
            },
          ]);
        }}
      />
    </Screen>
  );
}

const styles = StyleSheet.create({});
```

In this component:

*   We define a state variable `messages` to hold the list of messages. Initially, it contains some dummy messages.
    
*   We define a function `handleDelete` to remove a message from the list when the delete action is triggered.
    
*   Inside the `FlatList`, each message is rendered using the `ListItem` component, which displays the title, description, and an image.
    
*   The `ListItemDeleteAction` component is used to render the delete button, which triggers the `handleDelete` function when pressed.
    
*   The `renderRightActions` prop of `ListItem` component renders the delete action using the `ListItemDeleteAction` component.
    

In the `ListItem` component, import `Swipeable` from `react-native-gesture-handler/Swipeable` and wrap it around the entire component while passing the `renderRightActions` prop:

```javascript
import { Image, StyleSheet, TouchableHighlight, View } from 'react-native';
import React from 'react';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import AppText from './AppText';
import Colors from '../themes/Colors';

export default function ListItem({
  title,
  subTitle,
  image,
  onPress,
  renderRightActions,
}) {
  return (
    <Swipeable renderRightActions={renderRightActions}>
      <TouchableHighlight underlayColor={Colors.lightGrey} onPress={onPress}>
        <View style={styles.container}>
          <Image source={image} style={styles.image} />
          <View style={styles.detailsContainer}>
            <AppText style={styles.title}>{title}</AppText>
            <AppText style={styles.subTitle}>{subTitle}</AppText>
          </View>
        </View>
      </TouchableHighlight>
    </Swipeable>
  );
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    padding: 15,
  },
  image: {
    borderRadius: 35,
    width: 70,
    height: 70,
    marginRight: 10,
  },
  detailsContainer: {
    justifyContent: 'center',
  },
  title: {
    textTransform: 'capitalize',
    fontWeight: '500',
    paddingVertical: 5,
  },
  subTitle: {
    fontSize: 16,
    color: Colors.mediumGrey,
  },
});
```

The `renderRightActions` prop should be a function that returns a React component (ie: `ListItemDeleteAction`) representing the delete UI.

```javascript
import { StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
import React from 'react';
import Colors from '../themes/Colors';
import Icon from 'react-native-vector-icons/AntDesign';

export default function ListItemDeleteAction({ onPress }) {
  return (
    <TouchableWithoutFeedback onPress={onPress}>
      <View style={styles.container}>
        <Icon name="delete" color={Colors.white} size={30} />
      </View>
    </TouchableWithoutFeedback>
  );
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: Colors.dangerRed,
    width: 70,
    justifyContent: 'center',
    alignItems: 'center',
  },
  icon: {
    color: Colors.white,
  },
});
```

![iOS](https://cdn.hashnode.com/uploads/covers/69bdf388475ca1797455d60f/3acc3ea4-d1bb-49cd-af21-22207ca3ebc9.gif align="center")

The source code can be found [here](https://github.com/xinyingz2/ReactNativeDemos/tree/feature/swipeToDelete) on GitHub.

#### Step-by-Step Guide: Expo Project

Initialize a new Expo project:

```shell
expo init SwipeToDeleteExpo
```

**Install Dependencies:**

Add the required dependencies for swipe-to-delete:

```shell
expo install react-native-gesture-handler
```

**Implement Swipe-to-Delete:**

Follow the same steps as the React Native CLI project to implement swipe-to-delete using the `Swipeable` component. And **DO NOT FORGET** to import in your project’s entry file (e.g., `App.js`). Otherwise `Swipeable` won’t work!

**Testing:**

Run your Expo project using the Expo client app or on a physical device to test swipe-to-delete functionality.

#### Conclusion

By following the provided steps, you can seamlessly integrate swipe-to-delete functionality into your React Native projects, regardless of whether they are set up with React Native CLI or Expo. Enhance user experience and interaction by enabling users to efficiently manage lists with intuitive swipe gestures.

We encourage you to run the provided source code on your development environment. By doing so, you’ll gain a deeper understanding of how swipe-to-delete works in practice and how you can customize it to fit your specific project requirements.

Happy coding! ☀️
