How to add a search bar to a FlatList in React Native apps
In React Native applications, the FlatList is a component that’s used to efficiently display lists of data that are too big to fit on a single screen. It improves the application’s performance since the data is only rendered when it appears on the screen. However, as the list grows, finding specific items can become difficult. That’s where a search bar comes in handy. Adding a search bar to a FlatList is important for the following reasons:
It makes the application more user-friendly since the users can quickly find what they’re looking for instead of scrolling endlessly.
It saves users’ time and effort. They don’t have to manually search through a long list to locate an item.
It enhances the overall user experience of the application, making it more enjoyable to use.
The following is a step-by-step method of adding a search bar to a FlatList.
Import required components
The first step is to import the necessary components within the application. We need to import the FlatList along with other required components.
import React, { useState } from "react";import { SafeAreaView, View, Text, TextInput, FlatList, StyleSheet } from 'react-native';import {widthPercentageToDP as wp,heightPercentageToDP as hp,} from 'react-native-responsive-screen';
In the code snippet above:
Line 1: We import
useStateto manage states within the application.Line 2: We import
FlatListalong with other components to be used within the application.Lines 3–6: We import the
react-native-responsive-screenlibrary. It enables us to make the application responsive. You can read more about it in the official documentation. However, usage of this library is optional.
Set up initial data and state variables
Once the required components have been imported, we need to set up the state variables and initial data for the application. The initial data will be rendered by the FlatList.
const languages = [{id: 1,title: 'Python',},{id: 2,title: 'Java',},{id: 3,title: 'C++',},{id: 4,title: 'JavaScript',},{id: 5,title: 'Ruby',},{id: 6,title: 'Scala',},{id: 7,title: 'Rust',},{id: 8,title: 'Perl',},{id: 9,title: 'Swift',},{id: 10,title: 'TypeScript',},];const [data, setData] = useState(languages);const [searchText, setSearchText] = useState('');
In the code snippet above:
Lines 1–42: We define the
languagesarray. Thelanguagesarray contains a list of programming languages. Each language is represented as an object with anidandtitleproperty.Line 44: We define the state variable
dataand set it to thelanguagesarray. We will update this state variable according to the search text entered by the users.Line 45: We define the state variable
searchTextand set it to an empty string. We will update this state variable according to the search text entered by the users.
Render the UI
Once the steps above have been completed successfully, we need to render the UI. This includes the search bar and the rendering of the initial data.
const searchFunction = (text) => {setSearchText(text);}const renderItem = ({ item }) => (<View style={styles.box}><Text style={styles.title}> { item.title } </Text></View>);return (<SafeAreaView style={styles.container}><View style={styles.searchBarContainer}><Text style={styles.title}> Programming Languages </Text><TextInputstyle={styles.searchBar}placeholderTextColor="black"placeholder="Search available languages"value={searchText}onChangeText={text => searchFunction(text)}/></View><View style={styles.listDataContainer}><FlatListdata={ data }extraData={ data }showsVerticalScrollIndicator={ false }renderItem={ renderItem }keyExtractor={(item) => item.id}/></View></SafeAreaView>);const styles = StyleSheet.create({container: {flex: 1,},searchBarContainer: {flex: 1.5,backgroundColor: '#ffffff',alignItems: 'center',justifyContent: 'center',},title: {fontSize: wp(5.5),color: 'black',},searchBar: {width: wp(80),height: hp(6),borderWidth: wp(0.2),borderRadius: wp(3),borderColor: '#999999',backgroundColor: '#ffffff',marginTop: wp(7),paddingLeft: wp(4.5),fontSize: wp(4),color: 'black'},listDataContainer: {flex: 5,alignItems: 'center',justifyContent: 'center',backgroundColor: '#ffffff',},box: {width: wp(90),height: hp(20),borderWidth: wp(0.2),borderColor: 'black',alignItems: 'center',justifyContent: 'center',margin: wp(1)},});
The code snippet above shows part of the application’s code. This code is responsible for rendering the search bar and the initial data. Let’s see it in a bit more detail below:
Lines 1–3: We define the function
searchFunction. This function is called whenever the text within the search bar changes (line 20). At this stage, we only update the state variablesearchTextwithin this function. We’ll add the search logic later.Lines 5–9: We define the function
renderItem. This function is intended to be passed to theFlatListcomponent for rendering each item in thelanguagesarray defined previously. It returns aViewcomponent containing the title of the programming language displayed as text using theTextcomponent.Lines 12–32: We define the UI for the application. This includes the rendering of the title of the application (line 14), the search bar (lines 15–21), and the initial data (lines 24–30).
Lines 35–76: We define the styles of the application.
Define the search logic
Now we need to define the search logic. We need to filter the initial data based on the search text entered by the user within the search bar. Finally, this filtered data will be rendered by the FlatList component. The code snippet below shows how to do this.
const searchFunction = (text) => {setSearchText(text);text = text.toLowerCase();if (text === "") {setData(languages);}else {let filteredLanguages = languages.filter(language => (language.title.toLowerCase().startsWith(text)))setData(filteredLanguages);}}
In the code snippet above:
Lines 3–10: We modify the previously defined function
searchFunction. First, we convert the search text to lowercase. Then, if the search text is empty, we set the state variabledatato the initial data (languagesarray). Otherwise, we filter thelanguagesarray based on the search text entered by the user and set the state variabledatato the filtered data, i.e.,filteredLanguages.
Coding playground
The coding playground below shows the complete code we’ve discussed so far.
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.react_native_application;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceEventListener;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
/**
* Class responsible of loading Flipper inside your React Native application. This is the debug
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}
Note: You can download and execute the code example above on your local system or machine. Follow the official React Native documentation to set up the development environment. The code example above is for the Android operating system.
Free Resources