Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search Filter with React Native on FlatList

Tags:

I am trying to search through a flatlist based on a search bar text. The problem I am running into is that when the user mistypes...say they wanted to type "burger" but typed "burget" by mistake then it returns nothing as it should. When the user deletes the "t" then it should re-render the flatlist again with the last text matching the "burge" part.

note: using react-native-elements search bar which allows me to call the text with just e or event.

What I have so far in the Main.js file:

searchText = (e) => {
    let text = e.toLowerCase();
    let trucks = this.state.data;

    // search by food truck name
    let filteredName = trucks.filter((truck) => {
      return truck.name.toLowerCase().match(text); 
    });

    // if no match and text is empty
    if(!text || text === '') {
      console.log('change state');
        this.setState({
          data: initial
        });
      }
    // if no name matches to text output
    else if(!Array.isArray(filteredName) && !filteredName.length) {
      console.log("not name");
      this.setState({
        data: [],
      });
    }
    // if name matches then display
    else if(Array.isArray(filteredName)) {
      console.log('Name');
      this.setState({
        data: filteredName,
      });
    }
   };

<View style={styles.container}>
  <SearchBar
    round
    lightTheme
    containerStyle={styles.search}
    ref="search"
    textInputRef="searchText"
    onChangeText={this.searchText.bind(this)}
    placeholder='Search by Truck Name...'
   />
   <TruckList getTruck={(truck) => this.setTruck(truck)} truckScreen={this.truckScreen} data={this.state.data}/>
</View>

then the TruckList.JS:

export default class TruckList extends Component {
    // rendering truck screen
    renderTruckScreen = (item) => {
        this.props.truckScreen();
        this.props.getTruck(item);
    }

    render() {
        return(
            <List style={styles.list}>
                <FlatList
                    data={this.props.data}
                    renderItem={({ item }) => (
                        <ListItem
                            roundAvatar
                            avatar={{uri: item.pic1}}
                            avatarStyle={styles.avatar}
                            title={item.name}
                            titleStyle={styles.title}
                            subtitle={
                                <View style={styles.subtitleView}>
                                    <Text style={styles.subtitleFood}>{item.food}</Text>
                                    <View style={styles.subtitleInfo}>
                                        <Icon 
                                            name="favorite"
                                            size={20}
                                            color={"#f44336"}
                                            style={styles.subtitleFavorite}
                                        />
                                        <Text style={styles.subtitleFavoriteText}>{item.favorited} favorited</Text>
                                    </View>
                                </View>
                            }
                            onPress={() => this.renderTruckScreen(item)}
                        />
                    )}
                    keyExtractor={(item) => item.uid}
                    ListFooterComponent={this.footer}
                />
            </List>
        )
      }
    }

I have tried a few other ways to no avail. Also the only solutions I have seen working for React Native are with ListView which will be depreciated in time. So I am trying to do this with the new FlatList Component.

Thanks for your help!

like image 389
T. Evans Avatar asked Aug 14 '17 02:08

T. Evans


People also ask

How do you search data in FlatList in React Native?

To create a search bar on top of the FlatList, you need a component that scrolls away when the list is scrolled. One possible solution is to create a custom Search bar component and render it as the value of ListHeaderComponent prop in a FlatList. Open App. js and add the following prop to the list.

How do I search for filters in React Native?

To make a React Native Search Bar, we can also use SearchBar component provided by react-native-elements . To use SearchBar we have to install react-native-elements and react-native-vector-icons dependencies. For installation open the terminal and jump into your project using.

How do you search for data from an array in React Native?

To find an object in an array in React: Call the find() method on the array, passing it a function. The function should return an equality check on the relevant property. The find() method returns the first value in the array that satisfies the condition.

How do I add a search box in React Native?

// SearchBar. js import React from "react"; import { StyleSheet, TextInput, View, Keyboard, Button } from "react-native"; import { Feather, Entypo } from "@expo/vector-icons"; const SearchBar = ({clicked, searchPhrase, setSearchPhrase, setCLicked}) => { return ( <View style={styles. container}> <View style={ clicked ?


1 Answers

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!

like image 193
jeanverster Avatar answered Oct 26 '22 15:10

jeanverster