wake-up-neo.net

Suchfilter mit React Native in FlatList

Ich versuche, eine Flatliste basierend auf einem Suchleistentext zu durchsuchen. Das Problem, auf das ich stoße, ist, dass, wenn der Benutzer sich vertippt ... sagen, dass er "burger" eingeben wollte, aber versehentlich "burget" eingetippt hat, es dann nichts zurückgibt, wie es sollte. Wenn der Benutzer das "t" löscht, sollte er die Flatlist erneut mit dem letzten Text, der dem "burge" -Teil entspricht, erneut rendern.

hinweis: Verwenden Sie die Suchleiste für native Elemente, um den Text nur mit e oder event aufzurufen.

Was ich bisher in der Datei Main.js habe:

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>

dann die 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>
        )
      }
    }

Ich habe ein paar andere Möglichkeiten ausprobiert. Die einzigen Lösungen, die ich für React Native gesehen habe, sind ListView, die rechtzeitig abgeschrieben werden. Also versuche ich dies mit der neuen FlatList-Komponente.

Danke für Ihre Hilfe!

7
T. Evans

Ich bin heute auf dieses Problem gestoßen, als ich versuchte, eine Filter-/Suchfunktion für die neue FlatList-Komponente zu implementieren. So habe ich es gelöst:

Wenn Sie ein anderes Element im Status der übergeordneten Komponente namens noData erstellen, können Sie dies auf true setzen, wenn keine Ergebnisse vorhanden sind, die Ihrer Suche entsprechen, und dann Ihre FlatList bedingt wiedergeben.

Meine Implementierung unterscheidet sich etwas von Ihrer, aber wenn ich Ihren Code anpassen müsste, würde er ungefähr so ​​aussehen:

Suchtextfunktion:

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
      })
    }
  }

Übergeben Sie dann den noData-Bool an Ihre TruckList-Komponente: 

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

Rendern Sie dann Ihre FlatList in der TruckList-Komponente nur dann, wenn folgende Ergebnisse vorliegen: 

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

In diesem Fall sollten Sie sich um die Behandlung von Fehlern bei der Eingabe von Benutzern kümmern - da die Flatlist erneut gerendert wird, sobald keine Ergebnisse vorliegen, und der vorherige Suchstatus gespeichert wird, wenn Sie den Tippfehler entfernen. 

Lass es mich wissen, wenn das hilft!

13
jeanverster

Update:Dieses Blog kann Ihnen helfen, die Suche in einer FlatList besser zu verstehen.

FYI: Wenn Sie große Online-Daten haben, können Sie auch algolia verwenden.

Ich habe den obigen Code für mich angepasst, damit er richtig funktioniert. Der Grund ist, dass, wenn der Benutzer das letzte falsche Zeichen entfernt, der Code diese neue Zeichenfolge aus einer vorherigen Suchliste (Zustand) durchsucht, die nicht alle Objekte enthält, obwohl er aus einer vollständigen verfügbaren Liste suchen musste. Ich habe jetzt zwei Listen. Eine enthält eine vollständige Liste von Objekten und eine zweite enthält nur eine gerenderte Liste von Objekten, die sich bei der Suche ändern.

handleSearchInput(e){
    let text = e.toLowerCase()
    let fullList = this.state.fullListData;
    let filteredList = fullList.filter((item) => { // search from a full list, and not from a previous search results list
      if(item.guest.fullname.toLowerCase().match(text))
        return item;
    })
    if (!text || text === '') {
      this.setState({
        renderedListData: fullList,
        noData:false,
      })
    } else if (!filteredList.length) {
     // set no data flag to true so as to render flatlist conditionally
       this.setState({
         noData: true
       })
    }
    else if (Array.isArray(filteredList)) {
      this.setState({
        noData: false,
        renderedListData: filteredList
      })
    }
  }
6
Faisal Hassan

Für eine nützliche In-Memory-Suche sollten Sie die Anfangsdaten separat aufbewahren.

Ich habe eine einfachere Lösung dafür.

Diese Lösung für die speicherinterne Suche in FlatList-Daten verwendet die String.prototype .includes () -Methode zum Durchsuchen von Teilzeichenfolgen.

Den vollständigen Quellcode dieser Komponente finden Sie in dieser Übersicht. https://Gist.github.com/metehansenol/46d065b132dd8916159910d5e9586058

Mein Ausgangszustand;

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

Meine SearchBar-Komponente (stammt aus dem Paket "react-native-elements");

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

Meine Suchmethode;

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

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

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

Und zuletzt der DataSource-Ausdruck meiner FlatList.

<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}
  />}
/>

Viel Spaß beim Codieren ...

4
Metehan Senol

ref - https://medium.freecodecamp.org/how-to-build-a-react-native-flatlist-with-realtime-searching-ability-81ad100f6699

constructor(props) {
super(props);
this.state = {
  data: [],
  value: ""
};

this.arrayholder = [];
}

Nächstes Abrufen von Daten: -

_fetchdata = async () => {
const response = await fetch("https://randomuser.me/api?results=10");
const json = await response.json();
this.setState({ data: json.results });

this.arrayholder = json.results;
};

Als nächstes definieren Sie searchFilterFunction: -

searchFilterFunction = text => {
this.setState({
  value: text
});


const newData = this.arrayholder.filter(item => {
  const itemData = item.email.toLowerCase();

  const textData = text.toLowerCase();

  return itemData.indexOf(textData) > -1;
});

this.setState({ data: newData });
};

darstellung searchView: -

    <TextInput
      style={{ height: 40, borderColor: "gray", borderWidth: 1 }}
      onChangeText={text => this.searchFilterFunction(text)}
    />

Vergessen Sie nicht, TextInput von "react-native" zu importieren.

2
kvadityaaz

Hier ist meine Lösung:

Sie benötigen eine Sicherung Ihrer Daten

this.state = {
    data: [],
    backup: []
}

auf Suchmethode

search = txt => {
    let text = txt.toLowerCase()
    let tracks = this.state.backup
    let filterTracks = tracks.filter(item => {
    if(item.name.toLowerCase().match(text)) {
      return item
    }
  })
  this.setState({ data: filterTracks })
}

Erläuterung: Wenn Sie setState für Ihre Daten aufrufen, werden diese in den aktuellen Status versetzt und können nicht mehr geändert werden.

Daher werden Sicherungsdaten zur Filterung Ihrer Daten verwendet.

1
Jundell

Meine Suchmethode; von @ metehan-senol

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

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

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

die Suchmethode von könnte vereinfacht und Eslint-sicher sein

search = (searchText) => {
  const searched = searchText.toLowerCase();
  this.setState(prevState => ({
    searchText: searched,
    filteredData: prevState.data.filter(item =>
      item.description.toLowerCase().includes(searched)
    ),
  }));
}; 
0
ziSigmund

FYI: data ist die zu durchsuchende subtext. Dies ist eine grundlegende Suche, bei der die zu durchsuchenden Daten in jedem Listenelement eines Arrays durchsucht werden, das eine Kopie des tatsächlichen array/array von objects und schließlich dessen ist state wird festgelegt, ob Übereinstimmung zwischen 0 bis (actualArray.length-1) und der temporären arrayData gerendert wird oder nicht, wenn mindestens eine Übereinstimmung vorhanden ist, andernfalls actualArray

implementSearch(data) {
    temp = [];
    var count = 0;
    var searchData = data.toUpperCase();
    var arr = this.state.personDetail;
    for (var i = 0; i < arr.length; i++) {
      var actualData = arr[i].name.toUpperCase();
      if (actualData.includes(searchData)) {
        temp.Push(arr[i]);
        count++;
      }
    }
    this.setState({
      tempArray: temp,
      matches: count,
      searchValue: data
    });
  }

Hoffnung das hilft

0
Mohit Kumar