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:

  1. It makes the application more user-friendly since the users can quickly find what they’re looking for instead of scrolling endlessly.

  2. It saves users’ time and effort. They don’t have to manually search through a long list to locate an item.

  3. 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';
Importing required libraries

In the code snippet above:

  • Line 1: We import useState to manage states within the application.

  • Line 2: We import FlatList along with other components to be used within the application.

  • Lines 3–6: We import the react-native-responsive-screen library. 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('');
Setting up the initial data and state variables

In the code snippet above:

  • Lines 1–42: We define the languages array. The languages array contains a list of programming languages. Each language is represented as an object with an id and title property.

  • Line 44: We define the state variable data and set it to the languages array. We will update this state variable according to the search text entered by the users.

  • Line 45: We define the state variable searchText and 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>
<TextInput
style={styles.searchBar}
placeholderTextColor="black"
placeholder="Search available languages"
value={searchText}
onChangeText={text => searchFunction(text)}
/>
</View>
<View style={styles.listDataContainer}>
<FlatList
data={ 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)
},
});
Rendering the UI

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 variable searchText within 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 the FlatList component for rendering each item in the languages array defined previously. It returns a View component containing the title of the programming language displayed as text using the Text component.

  • 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);
}
}
Defining the search logic

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 variable data to the initial data (languages array). Otherwise, we filter the languages array based on the search text entered by the user and set the state variable data to 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());
      }
    }
  }
}
Coding playground

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

Copyright ©2025 Educative, Inc. All rights reserved