Contents
Written by Shalitha Suranga
React Native developers often have to use various form controls in their mobile apps. In some development scenarios, we may have to enable multi-selections in dropdown components.
For example, imagine you have an AI-based travel planner app and you want users to select their preferred destinations. You could list all available destinations in a multi-select dropdown to let the user choose multiple locations.
Besides inbuilt React Native form controls like buttons, switches, text inputs, and more, there are many open source community packages that offer pre-developed form controls. You can use existing multi-select dropdown packages or build one from scratch for your React Native app.
In this tutorial, weโll use the popular react-native-sectioned-multi-select
ย package โ a better alternative to the react-native-multiple-select
ย package. Weโll also explore how to build a multi-select dropdown from scratch with inbuilt React Native core components.
Letโs start by highlighting some standout features of the react-native-sectioned-multi-select
package and then explore its customization options using practical examples, going from basic to advanced. You can follow along with the library implementation below and check out the code for the from-scratch dropdown demo that weโll go over later.
Highlighted features of react-native-sectioned-multi-select
The react-native-sectioned-multi-select
library offers many useful features for adding cross-platform, customizable, and user-friendly multi-select dropdowns on Android and iOS platforms. Letโs explore some of its key features now.
A fully-featured, customizable component with better defaults
This library offers a UI/UX-friendly, modal-based, fully-featured multi-select dropdown with a searchable sectioned multi-select list. It comes with inbuilt styles and reasonable behavioral defaults that let you satisfy your design requirements with less code.
The library also exposes numerous props to allow you to adjust the dropdown componentโs default behavior and customize default styling.
UI/UX friendly design
This libraryโs multi-select dropdown component follows a better UI/UX-friendly design that improves user productivity. For example, the component offers an inbuilt feature that lets users select all items of a specific section by clicking on the particular section header.
Also, this multi-select dropdown component comes with a search box to help users find items quickly. Moreover, it renders the sectioned list on a modal to separate the multi-select UI from the main app screen.
Cross-platform and Expo support
The react-native-sectioned-multi-select
project contains pure JavaScript code without native modules written in platform-specific languages like Kotlin, so it works with any mobile platform and Expo.
Additionally, this dropdown component renders the same visuals on Android and iOS mobile platforms since it uses cross-platform React Native core components.
Creating multi-select dropdowns with react-native-sectioned-multi-select
We discussed the highlighted features that the react-native-sectioned-multi-select
library offers for creating multi-select dropdowns. Letโs use this library in a sample React Native project to explore its features and customizability options.
Iโll use an Expo project to demonstrate this library on the React Native framework. To get started with this tutorial, create a new Expo project like so:
npx create-expo-app MultiSelectDropdownDemo
cd MultiSelectDropdownDemo
You can also set up a new React Native project without Expo via the official React Native CLI and continue with the tutorial:
npx react-native init MultiSelectDropdownDemo
cd MultiSelectDropdownDemo
Installing required packages
Next, we need to install the react-native-sectioned-multi-select
npm package. This package needs an icon object from the react-native-vector-icons/MaterialIcons
, so we have to install @expo/vector-icons
as well. Install both packages into your newly created Expo with the following command:
npx expo install react-native-sectioned-multi-select @expo/vector-icons
If you donโt use Expo, you can install packages using the following commands:
npm install react-native-sectioned-multi-select react-native-vector-icons
# --- or ---
yarn add react-native-sectioned-multi-select react-native-vector-icons
Creating a basic multi-select dropdown
Letโs create a basic multi-select dropdown by using only the required props. Weโll add a dropdown component to select multiple vehicle types.
Add the following code to your App.js
file:
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
import SectionedMultiSelect from 'react-native-sectioned-multi-select';
import { MaterialIcons as Icon } from '@expo/vector-icons';
const items = [
{ name: 'Cars', id: 1},
{ name: 'Vans', id: 2},
{ name: 'SUVs', id: 3},
{ name: 'Motorbikes', id: 4 },
{ name: 'Trucks', id: 5},
];
export default function App() {
const [selectedItems, setSelectedItems] = useState([]);
console.log('Selected:', selectedItems);
return (
<View style={styles.container}>
<View>
<SectionedMultiSelect
items={items}
IconRenderer={Icon}
uniqueKey="id"
onSelectedItemsChange={setSelectedItems}
selectedItems={selectedItems}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
padding: 24,
},
});
If you donโt use Expo, make sure to import the icon object from react-native-vector-icons
as follows:
import Icon from 'react-native-vector-icons/MaterialIcons';
The above JSX code snippet creates a basic multi-select dropdown by importing the pre-developed SectionedMultiSelect
component. Here, we used the selectedItems
state field to hold an array of selected item indices, id
as the unique key, and name
as the display field.
You will see the following result when you run the above source code:
Once you press the Confirm button in the dropdown modal, youโll see selected items on the console as follows:
As the library name suggests, the react-native-sectioned-multi-select
library lets you group items into sections using child item arrays within dropdown item objects.
Create several vehicle models as sub-items using the items
property:
const items = [
{ name: 'Cars', id: 1,
items: [
{ name: 'Nissan Sunny', id: 100 },
{ name: 'Toyota Corolla', id: 101 },
{ name: 'Honda Civic', id: 102 },
]
},
{ name: 'Vans', id: 2,
items: [
{ name: 'Ford Transit', id: 200 },
{ name: 'Toyota Sienna', id: 201 },
]
},
{ name: 'SUVs', id: 3,
items: [
{ name: 'Toyota RAV4', id: 300 },
{ name: 'Ford Explorer', id: 301 },
]
},
{ name: 'Motorbikes', id: 4,
items: [
{ name: 'Kawasaki KX', id: 400 },
{ name: 'Ducati Panigale', id: 401 },
{ name: 'BMW Roadster', id: 402 },
]
},
];
Next, activate sub-items using the subKey
property of the SectionedMultiSelect
component:
<SectionedMultiSelect
items={items}
IconRenderer={Icon}
uniqueKey="id"
subKey="items"
onSelectedItemsChange={setSelectedItems}
selectedItems={selectedItems}
/>
Earlier, we could select multiple vehicle types from the dropdown. Now, itโs possible to select both vehicle types and vehicle models using the new dropdown, as shown in the following preview: As you can see in the above preview, by default, we can select vehicle types by tapping on the parent section header.
Basic visual customizations
By default, the SectionedMultiSelect
component displays selected items as tag elements, also called chips. Additionally, it shows several pre-defined text labels and implements some helpful control elements, like a Confirm button, search icon, and more, within the multi-select component.
You can customize these visuals using various props. For example, add the following component props to your app:
selectText="Choose some vehicles..."
searchPlaceholderText="Search vehicles..."
modalAnimationType="slide"
colors={{primary: '#c98422'}}
The above props use custom texts for select box and search placeholder labels, changes the default modal animation, and changes the primary theme color. Once you use the above props with the app code, you will see the following result: In the previous code snippet, we used only the primary
color key, but react-native-sectioned-multi-select
offers many color keys to help developers implement custom color schemes for multi-select dropdowns. Browse all supported color props and defaults in the official docs.
The react-native-sectioned-multi-select
library lets you add or modify child components within the main component with props. For example, headerComponent
and footerComponent
props let you embed extra components in the modal.
Use the following props in your multi-select component:
hideSearch={true}
expandDropDowns={true}
headerComponent={<MultiSelectHeader/>}
footerComponent={<MultiSelectFooter itemCount={selectedItems.length}/>}
Here, we added a header and footer child components to the multi-select modal via props. Also, the hideSearch
and expandDropDowns
props hide the search box and auto-expand all sections, respectively.
Next, we need to define two new React functional components as follows:
function MultiSelectHeader() {
return (
<View style={styles.multiSelectHeader}></View>
);
}
function MultiSelectFooter({ itemCount }) {
return (
<View>
<Text
style={styles.multiSelectFooterText}>
{itemCount} item(s) selected.</Text>
</View>
);
}
The above child components use several styles from the stylesheet, so update your app stylesheet with the following definitions:
multiSelectHeader: {
height: 24,
backgroundColor: '#c98422'
},
multiSelectFooterText: {
padding: 12,
marginTop: 12,
backgroundColor: '#eee'
},
Once you update your app source code, you will see a custom header and footer, as shown in the following preview: Similarly, the multi-select component offers searchIconComponent
, selectedIconComponent
, unselectedIconComponent
, and other props for customizing default visual segments of the component.
Basic behavioral customizations
This multi-select library implements UI/UX-friendly defaults, but you can adjust them according to your app design standards and guidelines with component props.
These behavioral customizations help developers tweak their apps for better productivity and usability. For example, setting true
for the readOnlyHeadings
prop disables selecting parent sections as selectable items in your React Native appโs multi-select dropdown.
Consider using the following prop in the SectionedMultiSelect
component for a demonstration:
readOnlyHeadings={true}
This prop disables selecting parent sections and expands or collapses section dropdowns as shown in the following preview: On the other hand, you can use the highlightChildren
prop to disable child item selections by auto-highlighting related child items once the parent section is selected.
If you make parent sections selectable in your multi-select dropdown, you can use parentChipsRemoveChildren
to remove all child items once the user clicks on a specific parent tagโs remove icon:
parentChipsRemoveChildren={true}
The above multi-select configuration behaves as follows: You can also configure the component to auto-select sub-items when you tap on a specific parent element by using the following setup:
selectChildren={true}
Now, itโs possible to select all sub-items of a parent element at once like so:
Using event handler props
The multi-select component exposes several event handler props to let developers attach event callback functions. The onSelectedItemsChange
event handler prop helped us in previous examples to get the currently selected item indices array.
SectionedMultiSelect
triggers the following events:
Event handler prop | Handler description |
---|---|
onSelectedItemObjectsChange | A function that returns the selected items as their original objects instead of an array of identifiers |
onCancel | A function that runs when the cancel button is pressed |
onConfirm | A function that runs when the confirm button is pressed |
onToggleSelector | A callback function that runs when the selector is toggled. It receives a boolean for the open/close state of the modal |
Adding custom styling definitions
As we learned in previous sections, the colors
prop offers a way to set a custom color theme for multi-select dropdowns. This multi-select component also offers several props to use custom font families for labels.
However, customizing colors and font families is not enough to satisfy unique design requirements, so this library lets you override internal styles via the styles
prop.
Assume that you need to customize the backdrop of the modal and the multi-select input box with custom styles. You can use a custom styles
object as follows for this requirement:
styles={{
backdrop: styles.multiSelectBackdrop,
selectToggle: styles.multiSelectBox
}}
Here are the styling definitions that you need to add to your stylesheet:
multiSelectBackdrop: {
backgroundColor: 'rgba(255, 183, 0, 0.2)',
},
multiSelectBox: {
borderWidth: 1,
borderRadius: 8,
borderColor: '#bbb',
padding: 12,
marginBottom: 12
},
The above styles
object customizes the backdrop and the input box as follows: Assume that you need to customize selected item tags with a custom styling setup, as shown in the following preview: To get the above multi-select style, you need to set custom styling definitions for chipContainer
and chipText
keys via the styles
object:
styles={{
backdrop: styles.multiSelectBackdrop,
selectToggle: styles.multiSelectBox,
chipContainer: styles.multiSelectChipContainer,
chipText: styles.multiSelectChipText,
}}
// in stylesheet
multiSelectChipContainer: {
borderWidth: 0,
backgroundColor: '#ddd',
borderRadius: 8
},
multiSelectChipText: {
color: '#222',
fontSize: 14.5
}
There are about 30 different style
object properties to customize the styling properties of the multi-select component. Browse all supported style object keys from the official documentation on GitHub.
Customizing the multi-select box text
Earlier, we used custom static text for the select box placeholder and search box placeholder by sending strings to selectText
and searchPlaceholderText
props.
By default, this library sets a dynamic text for the select box based on the following cases:
- Use the placeholder text if no item is selected
- If only one item is selected, use its display name
- If the user selects more than one item, use the placeholder and the โ( x selected )โ dynamic text together
Assume that your UI/UX standards and guidelines need to adjust the above logic as follows:
- Use the placeholder text if no item is selected
- Display selected items as an English sentence with
,
andand
connectors (e.g., Kawasaki KX, Ducati Panigale, and BMW Roadster) only if the selected vehicle count is greater than zero and less than three - Otherwise, display selected vehicles count as โx vehicle(s) selectedโ
Customizing select box text is possible with the renderSelectText
prop. Look at the following App
component code:
export default function App() {
const [selectedItems, setSelectedItems] = useState([]);
const [selectedItemObjects, setSelectedItemObjects] = useState([]);
console.log('Selected:', selectedItemObjects);
function renderSelectText() {
let c = selectedItems.length;
if(c <= 3) {
return selectedItemObjects.map((item) => item.name).
join(', ').replace(/, ([^,]*)$/, ' and $1')
}
if(c > 3) {
return `${c} vehicle(s) selected`;
}
return 'Choose some vehicles...';
}
return (
<View style={styles.container}>
<View>
<SectionedMultiSelect
items={items}
IconRenderer={Icon}
uniqueKey="id"
subKey="items"
selectedItems={selectedItems}
selectText="Choose some vehicles..."
searchPlaceholderText="Search vehicles..."
onSelectedItemsChange={setSelectedItems}
onSelectedItemObjectsChange={setSelectedItemObjects}
renderSelectText={renderSelectText}
showChips={false}
readOnlyHeadings={true}
/>
</View>
</View>
);
}
Run the above code, select several items, and look at the development preview:
How to implement Select all and Clear all buttons
This multi-select dropdown offers an inbuilt clear-all-items feature via the showRemoveAll
prop, which renders an additional tag for clearing all selected items without opening the modal. In some scenarios, we have to select or clear all items programmatically via other UI elements. This library offers two internal methods for this requirement.
Letโs implement two buttons to select and clear all items. To access these internal methods, first, you need to create a React ref as follows:
const ref = useRef(null);
...
<SectionedMultiSelect
ref={ref}
...
...
Next, add the following JSX content after the SectionedMultiSelect
component:
<View style={{paddingTop: 12}}>
<Button title="Select all" onPress={() => ref && ref.current && ref.current._selectAllItems()}
/>
<View style={{padding: 6}}/>
<Button title="Remove all" onPress={() => ref && ref.current && ref.current._removeAllItems()}
/>
</View>
Make sure that showChips
is set to {true}
in the multi-select component. Now, itโs possible to select and clear all items with two buttons, as shown in the following preview: Moreover, this multi-select dropdown component library exports the _toggleSelector
internal method to programmatically open and close the dropdown modal.
Adding item collection icons
Developers often use sectioned multi-select dropdowns to display items with categories, so adding icons for each category container becomes a common requirement. The react-native-sectioned-multi-select
library lets you set category icons by sending icon identifiers of the selected icon collection.
Letโs add some icons for the sample appโs categories. First, add icon keys to the items object as follows:
const items = [
{ name: 'Cars', id: 1, icon: 'directions-car',
items: [
{ name: 'Nissan Sunny', id: 100 },
{ name: 'Toyota Corolla', id: 101 },
{ name: 'Honda Civic', id: 102 },
]
},
{ name: 'Vans', id: 2, icon: 'airport-shuttle',
items: [
{ name: 'Ford Transit', id: 200 },
{ name: 'Toyota Sienna', id: 201 },
]
},
{ name: 'SUVs', id: 3, icon: 'car-repair',
items: [
{ name: 'Toyota RAV4', id: 300 },
{ name: 'Ford Explorer', id: 301 },
]
},
{ name: 'Motorbikes', id: 4, icon: 'motorcycle',
items: [
{ name: 'Kawasaki KX', id: 400 },
{ name: 'Ducati Panigale', id: 401 },
{ name: 'BMW Roadster', id: 402 },
]
},
];
Next, activate icon rendering by mentioning the icon property name as follows, along with a custom style for itemText
for better spacing:
<SectionedMultiSelect
iconKey="icon"
styles={{itemText: {marginLeft: 5, fontSize: 17}}}
...
...
Open the multi-select modal and look at category icons: Itโs possible to set icons for sub-items using the same icon
property within sub-item objects. This library lets you use icons from imported local images, web URLs, and custom icon packages, as explained in the official documentation on GitHub.
Loading multi-select items from the web
We used a hard-coded static items list with previous examples, but in real-world development scenarios, we often load data from RESTful services over the internet. Letโs fetch some items from JSONPlaceholder.
Update the component source code as follows:
export default function App() {
const [items, setItems] = useState(null);
const [selectedItems, setSelectedItems] = useState([]);
function loadUsers() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(users => setTimeout(() => setItems(users), 3000));
}
console.log('Selected:', selectedItems);
return (
<View style={styles.container}>
<View>
<SectionedMultiSelect
items={items}
IconRenderer={Icon}
uniqueKey="id"
subKey="items"
selectedItems={selectedItems}
selectText="Choose some users..."
searchPlaceholderText="Search users..."
onSelectedItemsChange={setSelectedItems}
onToggleSelector={(opened) => opened && loadUsers()}
loading={items === null}
/>
</View>
</View>
);
}
Here we used the inbuilt fetch
function to load users from the JSONPlaceholder RESTful web API. The loading
prop helps us display a loading animation for the fake three-second network latency.
Look at the following preview:
Creating a multi-select dropdown from scratch
The react-native-sectioned-multi-select
package is a fully-featured external library. So, it increases your app bundle size, as any other npm module.
`react-native-bundle-visualizer’ย detects only ~30 kilobytes of JavaScript bundle increment for this multi-select library, which is negligible compared to the size of the React Native framework. However, you can also build your own, customizable multi-select dropdown component from scratch and avoid using multi-select libraries.
Letโs see how to do this now. Here is a preview of a minimal multi-select dropdown built with inbuilt React Native core components: You can browse the complete source code of this multi-select dropdown implementation from this GitHub repository. This sample multi-select dropdown uses the following behavioral logic:
- Contains a select box with a dropdown icon that toggles up and down arrows based on the select box state
- Once you click on the select box, a list of items will appear as a dropdown
- The items list allows the user to select multiple items with a screen tap action
- The component uses a dark color background to differentiate a selected item from an unselected item
Youโll notice the following implementation details when you inspect the source:
- The
MultiSelect
reusable component exposesitems
andonSelectedItemsChange
props for basic functionality - Once an item is pressed, the component adds the selected item identifier to the
selectedItems
array and calls theonSelectedItemsChange
handler with the selected item identifiers
This multi-select dropdown is very minimal and has no animations, customization props, or advanced features like item search. You can extend it according to your design requirements by forking the GitHub repository.
Comparing multi-select dropdown implementation methods
Multi-select dropdown implementation is also possible with libraries like react-native-multiple-select
and react-native-multi-selectbox
. Letโs compare popular multi-select dropdown libraries and the from-scratch approach in a table:
Comparison factor | react-native-sectioned-multi-select | react-native-multiple-select | Without a library (i.e., react-native-multi-select-minimal) |
---|---|---|---|
Rendering of items | Uses a modal, so the item list wonโt interfere with other app controls | Doesnโt use a modal, so the item list can push down other form controls | Depends on the implementation method |
Inbuilt features | Offers many, well-organized features with better flexibility | Offers many features, but not feature-rich as react-native-sectioned-multi-select | None |
Pre-styled to boost developer-productivity | Yes | Yes | No |
Customizability | Very good | Good | No customizability restrictions as when using an external library |
Usage scenarios | Usable for creating multi-select dropdowns in any React Native app | Usable for creating multi-select dropdowns in any React Native app | When you need a minimal or domain-specific advanced multi-select dropdown |
According to the above comparison summary, react-native-sectioned-multi-select
offers a better solution for implementing customizable multi-select dropdowns in almost all development scenarios. You can learn advanced customizations and upcoming features by browsing its GitHub repository.
However, implementing a multi-select from scratch improves your React Native skills and offers the maximum development flexibility. So, for implementing minimal or domain-specific advanced multi-selects, building your own multi-select is undoubtedly a better option.
Conclusion
In this tutorial, we learned how to create multi-select dropdowns in React Native apps with practical examples. We discussed the fully-featured react-native-sectioned-multi-select
package and built one multi-select dropdown from scratch with React Native core components.
Regardless of the implementation method, consider using better UI/UX principles in multi-select components to offer better productivity for app users.
LogRocket: Instantly recreate issues in your React Native apps
LogRocketis a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket’s product analytics features surface the reasons why users don’t complete a particular flow or don’t adopt a new feature.
Start proactively monitoring your React Native apps โ try LogRocket for free.
[fluentform id="8"]