
React Native: make a draggable & swipeable list
- Tutorial
Today it’s hard to surprise anyone with the ability to swipe list items in mobile applications. One of our react-native applications also had such functionality, but recently there was a need to expand it with the ability to drag and drop list items. And since the process of finding a solution cost me a certain amount of nerve cells, I decided to file a short article to save valuable time for future generations.

In our application, we used the package to create a swipeable list
Search across the expanses of the Internet has given the three candidates:
Using the first package, it was not possible to run even the attached example (however, not only to me, the corresponding issue is indicated in issues ).
I had to tinker with the second package, but I managed to create a draggable & swipable list. However, the result was not inspired - the component was shamelessly blinking: blinking of the redrawing, falling of elements far beyond the list, or even their disappearance. It became clear that in this form it can not be used.
At first, the last package also behaved like a capricious lady, but then it turned out that I simply did not know how to cook it. Having picked up a key to the heart of this "lady", I managed to achieve an acceptable result.
In our project, there was a swipeable list to which you need to fasten drag and drop, but in practice it is better to start from the other edge: first make a draggable list and then add the ability to swipe.
Readers are supposed to know how to create a react-native project, so let's focus on creating the list we need. The example discussed below is TypeScript code.
So, let's start by installing the package:
We import the necessary modules:
Here
In a real application, this data will most likely come to your component from props or will be downloaded from the network, but in our case we will manage with little blood.
Since TypeScript is used in this example, we describe some entities:
The type
In this example, we will not get anything from props, so the interface
Since the component code is not very large, I will give it in its entirety:
The method
The method. This object includes the following fields:
The component for displaying the list item, in fact, is
Styles for all components are moved to separate files and are not given here, but they can be viewed in the repository .
The resulting result:

Well, we successfully coped with the first part, we proceed to the second part of the Marlezon ballet.
To add the ability to swipe the list items, we use the package
To get started, let's install it:
There is a component in this package
Note that the first View is drawn under the second.
Let's change the component code
First, we added a component
Secondly, we moved
Inside this View, a picture is drawn to determine if the language is a favorite. When you click on it, the value should be reversed, and since the data is in the parent component, you need to throw a callback here that performs this action.
Make the necessary changes to the parent component:
Sources of the project on GitHub .
The result is presented below:


In our application, we used the package to create a swipeable list
react-native-swipe-list-view
. The first thought was to take some package with drag'n'drop functionality and cross the hedgehog with a snake. Search across the expanses of the Internet has given the three candidates:
react-native-draggable-list
, react-native-sortable-list
and react-native-draggable-flatlist
.Using the first package, it was not possible to run even the attached example (however, not only to me, the corresponding issue is indicated in issues ).
I had to tinker with the second package, but I managed to create a draggable & swipable list. However, the result was not inspired - the component was shamelessly blinking: blinking of the redrawing, falling of elements far beyond the list, or even their disappearance. It became clear that in this form it can not be used.
At first, the last package also behaved like a capricious lady, but then it turned out that I simply did not know how to cook it. Having picked up a key to the heart of this "lady", I managed to achieve an acceptable result.
In our project, there was a swipeable list to which you need to fasten drag and drop, but in practice it is better to start from the other edge: first make a draggable list and then add the ability to swipe.
Readers are supposed to know how to create a react-native project, so let's focus on creating the list we need. The example discussed below is TypeScript code.
Making a draggable-list
So, let's start by installing the package:
yarn add react-native-draggable-flatlist
We import the necessary modules:
import React, { Component } from 'react'
import { View } from 'react-native'
import styles from './styles'
import DraggableFlatList, { RenderItemInfo, OnMoveEndInfo } from 'react-native-draggable-flatlist'
import ListItem from './components/ListItem'
import fakeData from './fakeData.json'
Here
DraggableFlatList
is the component from the installed package that implements the drag and drop function, ListItem
our component for displaying the list item (the code will be presented below), the fakeData
json file containing the fake data - in this case, an array of objects of the form:{"id": 0, "name": "JavaScript", "favorite": false}
In a real application, this data will most likely come to your component from props or will be downloaded from the network, but in our case we will manage with little blood.
Since TypeScript is used in this example, we describe some entities:
type Language = {
id: number,
name: string,
favorite: boolean,
}
interface AppProps {}
interface AppState {
data: Array
}
The type
Language
tells us which fields the list items will have. In this example, we will not get anything from props, so the interface
AppProps
is trivial, and in the story we will store an array of objects Language
, which is indicated in the interface AppState
. Since the component code is not very large, I will give it in its entirety:
App component code
class App extends Component {
constructor(props: AppProps) {
super(props)
this.state = {
data: fakeData,
}
}
onMoveEnd = ({ data }: OnMoveEndInfo) => {
this.setState({ data: data ? [...data] : [] })
}
render() {
return (
item.id.toString()}
scrollPercent={5}
onMoveEnd={this.onMoveEnd}
/>
)
}
renderItem = ({ item, move, moveEnd, isActive }: RenderItemInfo) => {
return (
)
}
}
The method
onMoveEnd
is called when the movement of the element is finished. In this case, we need to put the list with the new order of elements in the state, so we call the method this.setState
. The method
renderItem
is used to display a list item and takes an object of type RenderItemInfoitem
- the next element of the array passed as data to the list,move
andmoveEnd
- the functions called when the list item is moved, the component provides these functionsDraggableFlatList
,isActive
- a field of a logical type that determines whether the item is draggable at the moment.
The component for displaying the list item, in fact, is
TouchableOpacity
which, when pressed long, calls move
, and when released, - moveEnd
.ListItem component code
import React from 'react'
import { Text, TouchableOpacity } from 'react-native'
import styles from './styles'
interface ListItemProps {
name: string,
move: () => void,
moveEnd: () => void,
isActive: boolean,
}
const ListItem = ({ name, move, moveEnd, isActive }: ListItemProps) => {
return (
{name}
)
}
export default ListItem
Styles for all components are moved to separate files and are not given here, but they can be viewed in the repository .
The resulting result:

Add the ability to swipe
Well, we successfully coped with the first part, we proceed to the second part of the Marlezon ballet.
To add the ability to swipe the list items, we use the package
react-native-swipe-list-view
. To get started, let's install it:
yarn add react-native-swipe-list-view
There is a component in this package
SwipeRow
, which, according to the documentation, should include two components:
Note that the first View is drawn under the second.
Let's change the component code
ListItem
.ListItem component code
import React from 'react'
import { Text, TouchableOpacity, View, Image } from 'react-native'
import { SwipeRow } from 'react-native-swipe-list-view'
import { Language } from '../../App'
import styles from './styles'
const heart = require('./icons8-heart-24.png')
const filledHeart = require('./icons8-heart-24-filled.png')
interface ListItemProps {
item: Language,
move: () => void,
moveEnd: () => void,
isActive: boolean,
onHeartPress: () => void,
}
const ListItem = ({ item, move, moveEnd, isActive, onHeartPress }: ListItemProps) => {
return (
{item.name}
)
}
export default ListItem
First, we added a component
SwipeRow
with a property rightOpenValue
that determines the distance over which the element can be swiped. Secondly, we moved
SwipeRow
ours inside TouchableOpacity
and added the View, which will be drawn under this button. Inside this View, a picture is drawn to determine if the language is a favorite. When you click on it, the value should be reversed, and since the data is in the parent component, you need to throw a callback here that performs this action.
Make the necessary changes to the parent component:
App component code
import React, { Component } from 'react'
import { View } from 'react-native'
import styles from './styles'
import DraggableFlatList, { RenderItemInfo, OnMoveEndInfo } from 'react-native-draggable-flatlist'
import ListItem from './components/ListItem'
import fakeData from './fakeData.json'
export type Language = {
id: number,
name: string,
favorite: boolean,
}
interface AppProps {}
interface AppState {
data: Array
}
class App extends Component {
constructor(props: AppProps) {
super(props)
this.state = {
data: fakeData,
}
}
onMoveEnd = ({ data }: OnMoveEndInfo) => {
this.setState({ data: data ? [...data] : [] })
}
toggleFavorite = (value: Language) => {
const data = this.state.data.map(item => (
item.id !== value.id ? item : { ...item, favorite: !item.favorite }
))
this.setState({ data })
}
render() {
return (
item.id.toString()}
scrollPercent={5}
onMoveEnd={this.onMoveEnd}
/>
)
}
renderItem = ({ item, move, moveEnd, isActive }: RenderItemInfo) => {
return (
this.toggleFavorite(item)}
/>
)
}
}
export default App
Sources of the project on GitHub .
The result is presented below:
