Search Filter with React Native on FlatList

For a useful in-memory search you should keep initial data seperately.

I have more simple solution for this.

This solution for in-memory search on FlatList's data and uses it String.prototype​.includes() method to search substring.

You can find full source code of this component in this gist; https://gist.github.com/metehansenol/46d065b132dd8916159910d5e9586058

My initial state;

this.state = {
  searchText: "",
  data: [],
  filteredData: []
};

My SearchBar component (it comes from react-native-elements package);

<SearchBar
  round={true}
  lightTheme={true}
  placeholder="Search..."
  autoCapitalize='none'
  autoCorrect={false}
  onChangeText={this.search}
  value={this.state.searchText}
/>

My search method;

search = (searchText) => {
  this.setState({searchText: searchText});

  let filteredData = this.state.data.filter(function (item) {
    return item.description.includes(searchText);
  });

  this.setState({filteredData: filteredData});
};

And last my FlatList's DataSource expression;

<FlatList
  data={this.state.filteredData && this.state.filteredData.length > 0 ? this.state.filteredData : this.state.data}
  keyExtractor={(item) => `item-${item.id}`}
  renderItem={({item}) => <ListItem
    id={item.id}
    code={item.code}
    description={item.description}
  />}
/>

Happy coding...


I came across this same issue today when trying to implement a filter / search function on the new FlatList component. This is how I managed to solve it:

By creating another item in the state of the parent component called noData, you can set that to true when there are no results that match your search and then render your FlatList conditionally.

My implementation is slightly different to yours, but if I had to adjust your code it would look something like this:

Searchtext function:

searchText = (e) => {
    let text = e.toLowerCase()
    let trucks = this.state.data
    let filteredName = trucks.filter((item) => {
      return item.name.toLowerCase().match(text)
    })
    if (!text || text === '') {
      this.setState({
        data: initial
      })
    } else if (!Array.isArray(filteredName) && !filteredName.length) {
      // set no data flag to true so as to render flatlist conditionally
      this.setState({
        noData: true
      })
    } else if (Array.isArray(filteredName)) {
      this.setState({
        noData: false,
        data: filteredName
      })
    }
  }

Then pass the noData bool to your TruckList component:

<TruckList getTruck={(truck) => this.setTruck(truck)} 
truckScreen={this.truckScreen} data={this.state.data} noData={this.state.noData}/>

Then render your FlatList in the TruckList component only if there are results:

<List style={styles.list}>
{this.props.noData ? <Text>NoData</Text> : <FlatList {...} />}         
</List>

That should then take care of handling user typing errors - as it will re-render the flatlist as soon as there are no results, and will remember the previous search state when you remove the typing error..

Let me know if that helps!