React Native: Swipeable Row component with actions
Tags: reactnative, tutorial, ui, mobile
Published: 2024-03-02 12:41:28

In this tutorial I will explain how to implement a UI element popular on iOS devices - **swipeable row with actions**. We will use the `react-native-gesture-handler` library.

![ShoppingList](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pm5aco2bse7lzi4kf9kv.jpg)

![ShoppingListSwipe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmfltwut3b34g4q3cj9n.jpg)

Let's look at a **singular row component**:

![Row](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uec6ujul79ltp6i0fbjv.jpg)

```ts
<View style={styles.container}>
        <TouchableOpacity style={styles.cardContainer} activeOpacity={1}>
          <Image
            source={{
              uri: product?.images?.length
                ? product.images[0]
                : settings.PRODUCT_IMAGE_PLACEHOLDER,
            }}
            style={styles.imageMini}
          />

          <View style={styles.rightSide}>
            <Text style={styles.title} numberOfLines={2}>
              {product.title}
            </Text>

            <View style={styles.buttonAndPriceContainer}>
              <MiniProductButton
                quantity={
                  product.inCartCount ? (product.inCartCount as number) : 0
                }
                onPressAdd={() => {}}
                onPressRemove={() => {}}
              />

              <Text style={styles.priceText} numberOfLines={1}>
                {formatPrice(product)}
              </Text>
            </View>
          </View>
        </TouchableOpacity>
      </View>
```

> The view should have a background color (or obscure the background in some other way), otherwise left and right actions will be visible on the screen the moment the user starts swiping!

![No background color](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkty24nkhqqhyt69fgwu.jpg)

```ts
container: {
    alignSelf: 'stretch',
    padding: 12,
    flex: 1,
    backgroundColor: palette.screenBackground,
  },
```

First, we need to wrap this view in `<Swipeable>`.
Then, we need to create a function that will return a view that will be rendered when the user swipes to the left.

![Right actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gb3jhz23bqpq1wlsxj37.jpg)

```ts
const renderRightActions = () => {
    return (
      <View style={styles.rightActions}>
        <TouchableOpacity
          style={styles.favoriteButton}
          onPress={onFavoritePressed}>
          <IconFavoriteBig />
          <Text style={styles.textInSwipe}>Favorite</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.deleteButton}
          onPress={onDeleteItemPressed}>
          <IconDelete />
          <Text style={styles.textInSwipe}>Remove</Text>
        </TouchableOpacity>
      </View>
    );
  };
```

Now, we need to pass this function to `<Swipeable>` as `renderRightActions` prop. The complete code of the component:

```ts
return (
    <Swipeable renderRightActions={renderRightActions}>
      <View style={styles.container}>
        <TouchableOpacity style={styles.cardContainer} activeOpacity={1}>
          <Image
            source={{
              uri: product?.images?.length
                ? product.images[0]
                : settings.PRODUCT_IMAGE_PLACEHOLDER,
            }}
            style={styles.imageMini}
          />

          <View style={styles.rightSide}>
            <Text style={styles.title} numberOfLines={2}>
              {product.title}
            </Text>

            <View style={styles.buttonAndPriceContainer}>
              <MiniProductButton
                quantity={
                  product.inCartCount ? (product.inCartCount as number) : 0
                }
                onPressAdd={() => {}}
                onPressRemove={() => {}}
              />

              <Text style={styles.priceText} numberOfLines={1}>
                {formatPrice(product)}
              </Text>
            </View>
          </View>
        </TouchableOpacity>
      </View>
    </Swipeable>
```
**This is it!** The actions will appear after the user swipes the component:

![Right actions row](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80qn5oes2mzhcit5y3vx.jpg)

You can create **left actions** in the same way and pass them as `renderLeftActions`.

There are also some **useful props and methods** that you should check out, such as `friction` or `overshootLeft/Right`.

Information about **all available props and methods** can be found  [here](https://docs.swmansion.com/react-native-gesture-handler/docs/components/swipeable/).

If you have any suggestions on how to improve this article, I'd love to hear them in the comments!