Search Bar in React Native
Search Bar
~9 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
A search bar is at its core a TextInput with a magnifying-glass icon, live filtering of a list on every keystroke, and a "clear" button – not its own React Native API, but a composition of building blocks you already know.
1. Description
The filtering itself is plain JavaScript: on every change of the search text, the original data list is checked against the (lowercased) search text with Array.prototype.filter(), and the result is stored in state – React Native itself has nothing to do with this part.
2. Short example
const [query, setQuery] = useState('');
const filtered = cities.filter((c) =>
c.toLowerCase().includes(query.toLowerCase())
);3. Complete project: a city search
npx create-expo-app searchbar-demo
cd searchbar-demoimport { useState, useMemo } from 'react';
import { View, TextInput, FlatList, Text, TouchableOpacity, StyleSheet } from 'react-native';
const CITIES = [
'Berlin', 'Hamburg', 'Munich', 'Cologne', 'Frankfurt', 'Stuttgart',
'Dusseldorf', 'Leipzig', 'Dortmund', 'Essen', 'Bremen', 'Dresden',
];
export default function App() {
const [query, setQuery] = useState('');
const filtered = useMemo(
() => CITIES.filter((city) => city.toLowerCase().includes(query.toLowerCase())),
[query]
);
return (
<View style={styles.container}>
<View style={styles.searchBar}>
<Text style={styles.icon}>????</Text>
<TextInput
style={styles.input}
placeholder="Search a city…"
value={query}
onChangeText={setQuery}
autoCapitalize="none"
clearButtonMode="while-editing"
/>
{query.length > 0 && (
<TouchableOpacity onPress={() => setQuery('')}>
<Text style={styles.clear}>✕</Text>
</TouchableOpacity>
)}
</View>
<FlatList
data={filtered}
keyExtractor={(item) => item}
renderItem={({ item }) => <Text style={styles.row}>{item}</Text>}
ListEmptyComponent={<Text style={styles.empty}>No city found.</Text>}
/>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, paddingTop: 60, paddingHorizontal: 16 },
searchBar: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#f3f4f6', borderRadius: 10, paddingHorizontal: 12, marginBottom: 12 },
icon: { marginRight: 8 },
input: { flex: 1, height: 44, fontSize: 16 },
clear: { color: '#9ca3af', fontSize: 16, paddingHorizontal: 6 },
row: { fontSize: 16, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#e5e7eb' },
empty: { textAlign: 'center', marginTop: 24, color: '#9ca3af' },
});4. Explanation
useMemo(() => ..., [query])– only recomputes the filtered list whenqueryactually changes, not on every re-render of the component for other reasons.toLowerCase()on BOTH sides of the comparison – without it, "munich" (lowercase) would not match "Munich".clearButtonMode="while-editing"is iOS-specific (a native "×" button inside the field); the additional customTouchableOpacityclear button provides consistent behavior on Android too.ListEmptyComponentfrom theFlatListchapter is reused here for the "no results" message.