Do you want to know how we can select or deselect multiple Items inside react-native. Then let’s see how we can do that using TouchableOpacity
and onLongPress
.
For this project I am using bare react-native cli but it also works with expo cli as well.
You can check out this same post on ndpniraj
Content we will be covering in this post.
- Over view of the project
- Initializing Project
- Giving shape to our project
- Creating a ListItem component
- Adding all the logics
- Deselect on second tap
Over View of the project
Before we write any code for our react native multi select project, let’s understand what we want and how we can achieve our goal.
The feature that we want to add inside our project is that.
- If the user just taps on the list item we want to open or navigate to a different component.
- If the user taps and holds the finger then we want to select that list item and enable the multiple selection option.
- Also if the user taps outside or in an empty space we want to deselect all.
Initialize a Project
You can initialize your project using npx react-native init MultipleSelect
command if you are using react-native-cli like me or you can use expo init
or you can use the existing react native project where you want to add this multiple select option.
After initializing your project you can run it inside an emulator or inside a physical device and please don’t ask me how to do that because you are already a pro.
Giving Shape
To create this multiple selection option I will be using some fake data with fake names and contact numbers. If you also want to use that you can copy from the example below (last of the page).
...
const App = () => {
return (
<Pressable>
<FlatList
data={data}
renderItem={({item}) =><Text>{item.name}</Text>}
keyExtractor={item => item.id}
/>
</Pressable>
);
};
...
Don’t worry bros and sis let me explain what is going on here. Here I am using the FlastList component to render our fake data and I hope you already know how it works. Like data, renderItem and all.
After that the new thing is that I am wrapping the FlatList component inside this new Pressable component. That is because we want to deselect all the selections if we tap outside of the list. It’s like Touchable components but it's a new thing inside react-native family.
Creating a ListItem component
Let’s create a beautiful component to render these list items and add some styles.
...
const ListItem = ({item, selected, onPress, onLongPress}) => (
<>
<TouchableOpacity
onPress={onPress}
onLongPress={onLongPress}
style={styles.listItem}>
<View style={{padding: 8}}>
<Text style={{fontSize: 22, color: '#fff'}}>{item.name}</Text>
<Text style={{color: '#989BA1'}}>{item.contact}</Text>
</View>
{selected && <View style={styles.overlay} />}
</TouchableOpacity>
</>
);
const App = () => {
const handleOnPress = () => console.log('pressed');
const handleLongPress = () => console.log('activete long press');
return (
<Pressable style={{flex: 1, padding: 15}}>
<FlatList
data={data}
renderItem={({item}) => (
<ListItem
onPress={handleOnPress}
onLongPress={handleLongPress}
item={item}
/>
)}
keyExtractor={item => item.id}
/>
</Pressable>
);
};
...
Here we have this beautiful ListItem component to render our list items and we are using TouchableOpacity so that we can do our secret tasks. Just joking, it is here to listen to user touch events.
As you can see clearly inside this ListItem component we are accepting an item, selected, onPress and onLongPress prop.
Item will be the actual item with data like name and contact which we will render inside here. Selected will be the condition which we are using to display an overlay on top of our list items.
This overlay is just a View component with position absolute, height and width 100% and color with half opacity. The rest of the other code is I think self explanatory.
Now our project looks like this.
Now we will add a state called selectedItems inside our project so that we can add the multi select options. Feel free to use any name you like.
After that we will attach onPress and onLongPress prop and because we want to know which list item is currently pressed so we will use the inline function and pass the current item like here in example.
...
<FlatList
data={data}
renderItem={({item}) => (
<ListItem
onPress={() => handleOnPress(item)}
onLongPress={() => handleLongPress(item)}
selected={getSelected(item)}
item={item}
/>
)}
...
Also you may have noticed that selected={getSelected(item)}. This is to find a render that overlay if the list items are selected.
Adding all the logics
...
const App = () => {
const [selectedItems, setSelectedItems] = useState([]);
const handleLongPress = contact => {
selectItems(contact)
};
const handleOnPress = contact => {
if (selectedItems.length) {
return selectItems(contact)
}
// here you can add you code what do you want if user just do single tap
console.log('pressed');
};
const getSelected = contact => selectedItems.includes(contact.id);
const deSelectItems = () => setSelectedItems([]);
const selectItems = (item) => {
setSelectedItems([...selectedItems, item.id]);
}
...
Here comes the actual magic guys inside this example we have everything to select multiple items inside our react native app.
First we have this selectedItems
state and the default value is obviously an empty array because we don’t want to select anything at the beginning.
If you come to the end of this code block there we have a method called selectItems
. Inside this method we are just accepting an item and storing that item’s id inside the selectedItems
array.
Then we have handleLongPress
and handleOnPress
methods as well.
Inside handleLongPress
we are just calling the selectItems
method. So that is why we can remove this handleLongPress and directly use the selectItems
method inside onLongPress
prop. Which you will find inside the final code.
Inside handleOnPress
we are checking if there are already some selected items then we are selecting more but if not then you can see that console log and the comment. You can do whatever you want.
Then we have another method getSelected
inside this method we are just checking if the current item is already inside selectedItems
or not. If yes then it will return true otherwise returns false.
Then we have the deSelectItems
and inside this method we are just resetting the value of selectedItems
state to an empty array. And we will attach this method to the Pressable
components onPress
prop.
Deselect on second tap
With these lines of code now it will select multiple items but if you try to deselect the selected one then it will do nothing. So for that we need to update our selectItems
method. Like below.
const selectItems = item => {
if (selectedItems.includes(item.id)) {
const newListItems = selectedItems.filter(listItem => listItem !== item.id);
return setSelectedItems([...newListItems]);
}
setSelectedItems([...selectedItems, item.id]);
};
Now here we have this updated selectItems
method. Where we are first checking if the currently tapped item is already inside the selectedItems
array or not.
If yes then we are removing it from the selectedItems
list by using array filter method and returning the code execution. If not then we are adding that list item inside our selectedItems
state.
Now we made our final project. Multi select using react-native. Now you can use this selectedItems
state to render any other components if you want.
Like if you want to open any options, delete icons or anything that you want you can use if there is selectedItems.length
then do this or that.
Ok this is it for this post. Here is the complete code.
import React, {useState} from 'react';
import {
StyleSheet,
FlatList,
Pressable,
Text,
TouchableOpacity,
View,
} from 'react-native';
const data = [
{name: 'Rohan', contact: '1111111111', id: '1'},
{name: 'Mohan', contact: '2222222222', id: '2'},
{name: 'Sohan', contact: '3333333333', id: '3'},
{name: 'Hohan', contact: '4444444444', id: '4'},
{name: 'Dohan', contact: '5555555555', id: '5'},
{name: 'Pohan', contact: '6666666666', id: '6'},
];
const ListItem = ({item, selected, onPress, onLongPress}) => (
<>
<TouchableOpacity
onPress={onPress}
onLongPress={onLongPress}
style={styles.listItem}>
<View style={{padding: 8}}>
<Text style={{fontSize: 22, color: '#fff'}}>{item.name}</Text>
<Text style={{color: '#989BA1'}}>{item.contact}</Text>
</View>
{selected && <View style={styles.overlay} />}
</TouchableOpacity>
</>
);
const App = () => {
const [selectedItems, setSelectedItems] = useState([]);
const handleOnPress = contact => {
if (selectedItems.length) {
return selectItems(contact);
}
// here you can add you code what do you want if user just do single tap
console.log('pressed');
};
const getSelected = contact => selectedItems.includes(contact.id);
const deSelectItems = () => setSelectedItems([]);
const selectItems = item => {
if (selectedItems.includes(item.id)) {
const newListItems = selectedItems.filter(
listItem => listItem !== item.id,
);
return setSelectedItems([...newListItems]);
}
setSelectedItems([...selectedItems, item.id]);
};
return (
<Pressable onPress={deSelectItems} style={{flex: 1, padding: 15}}>
<FlatList
data={data}
renderItem={({item}) => (
<ListItem
onPress={() => handleOnPress(item)}
onLongPress={() => selectItems(item)}
selected={getSelected(item)}
item={item}
/>
)}
keyExtractor={item => item.id}
/>
</Pressable>
);
};
const styles = StyleSheet.create({
container: {},
listItem: {
backgroundColor: '#252628',
marginBottom: 10,
borderRadius: 5,
overflow: 'hidden',
},
overlay: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(255,0,0,0.5)',
},
});
export default App;
Top comments (0)