Wie wird die Flatlist neu gerendert?

86

Im Gegensatz zu ListView können wir this.state.datasource aktualisieren. Gibt es eine Methode oder ein Beispiel, um FlatList zu aktualisieren oder neu zu rendern?

Mein Ziel ist es, den Textwert zu aktualisieren, wenn der Benutzer die Taste drückt ...

renderEntries({ item, index }) {
    return(
        <TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
             <Text>{this.state.data[index].value}</Text>
        </TouchableHighlight>
    )
}

<FlatList 
    ref={(ref) => { this.list = ref; }} 
    keyExtractor={(item) => item.entry.entryId} 
    data={this.state.data} 
    renderItem={this.renderEntries.bind(this)} 
    horizontal={false} />
Shalonteoh
quelle
7
In den Dokumenten für FlatList heißt es: "Dies PureComponentbedeutet, dass es nicht erneut gerendert wird, wenn die Requisiten flach bleiben. Stellen Sie sicher, dass alles, von dem Ihre renderItemFunktion abhängt, als Requisite übergeben wird, die nicht ===nach Aktualisierungen erfolgt. Andernfalls wird Ihre Benutzeroberfläche möglicherweise nicht aktualisiert." Dies schließt den dataStatus der Requisite und der übergeordneten Komponente ein. " Folgen Sie diesem Rat?
Jordan läuft
3
Egal mit was ich es versucht habe extraDataund shouldItemUpdate, ich konnte die Liste nicht zum erneuten Rendern bringen. Am Ende habe ich den Status gelöscht, darauf gewartet, dass er gerendert wird, und dann den Status aktualisiert. this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Joshua Pinter

Antworten:

186

Verwenden Sie die extraDataEigenschaft für Ihre FlatList-Komponente.

Wie in der Dokumentation angegeben:

Durch die Weitergabe extraData={this.state}an stellen FlatListwir sicher FlatList, dass sich bei den state.selectedÄnderungen neu gerendert wird . Ohne diese Requisite zu setzen, FlatListwürde ich nicht wissen, dass es irgendwelche Elemente neu rendern muss, da es auch eine ist PureComponentund der Requisitenvergleich keine Änderungen zeigt.

ED209
quelle
34
Ich benutze Redux und sende in diesem Fall Daten wie data={this.props.searchBookResults}und funktioniert weder extraData={this.state}noch extraData={this.props}für mich. Und data={this.props.searchBookResults}funktioniert auch nicht. Was ist zu tun ?
Sujit
8
Verwenden Sie extraData: um Ihre <FlatList> zu aktualisieren... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
Nein,
9
Ich habe mit dem gleichen Problem zu kämpfen. Es ist egal, was ich weitergebe extraData, die Komponente wird nicht aktualisiert :(
Denis Cappelini
2
@DenisCappelini, stellen Sie sicher, dass sich die an die extraDataRequisite übergebenen Daten ändern, wenn untergeordnete Elemente erneut gerendert werden müssen. Wenn beispielsweise Listenelemente aktiv / inaktiv sein können, stellen Sie sicher, dass die Statusvariable, ob Teil des this.stateObjekts oder des this.propsObjekts, darin enthalten sein soll extraData. Es könnte ein Cursor oder ein Array von aktiven Elementen usw. sein.
Emperor_Earth
1
@Sujit Ich hatte das gleiche Problem, aber dann wurde mir klar, dass ich das implementiert shouldComponentUpdate()hatte. Sobald ich das aktualisiert oder vollständig auskommentiert hatte, funktionierten die Dinge genau wie in der Dokumentation beschrieben.
JanithaR
51

Für eine schnelle und einfache Lösung Versuchen Sie:

  1. Setzen Sie zusätzliche Daten auf einen booleschen Wert.

    extraData = {this.state.refresh}

  2. Schalten Sie den Wert des booleschen Status um, wenn Sie die Liste erneut rendern / aktualisieren möchten

    this.setState({ 
        refresh: !this.state.refresh
    })
    
Hradesh Kumar
quelle
Genau das brauche ich, da ich der Daten-Requisite Daten hinzufügen werde. Das ist auch eine super seltsame Implementierung durch das React-Native-Team ... es wäre viel sinnvoller, eine Aktualisierungsfunktion oder -eigenschaft für Daten zu haben. IE : this.data.refresh(). Stattdessen setzen wir einen Booleschen Wert und ändern ihn. Der Boolesche Wert selbst hat keine Bedeutung. Worum geht es also? ... (Es gibt keinen anderen
Grund
@HradeshKumar Ich mache es, aber das letzte Element in Data kann nicht verschwinden!
DevAS
Das funktioniert wie ein Zauber, aber ich weiß immer noch nicht, warum this.state.userses nicht funktioniert hat, obwohl ich bei einigen Benutzern eine Flagge geändert habe.
shitammakwana.me
21

Oh, das ist einfach, benutze es einfach extraData

Sie sehen, wie zusätzliche Daten hinter den Kulissen funktionieren: Die FlatList oder die VirtualisedList prüfen nur, ob sich das Objekt über eine normale onComponentWillReceivePropsMethode geändert hat .

Alles, was Sie tun müssen, ist sicherzustellen, dass Sie etwas geben, das sich am ändert extraData.

Folgendes mache ich:

Ich verwende immutable.js, also übergebe ich nur eine Map (unveränderliches Objekt), die alles enthält, was ich sehen möchte.

<FlatList
    data={this.state.calendarMonths}
    extraData={Map({
        foo: this.props.foo,
        bar: this.props.bar
    })}
    renderItem={({ item })=>((
        <CustomComponentRow
            item={item}
            foo={this.props.foo}
            bar={this.props.bar}
        />
    ))}
/>

Auf diese Weise wird unser Datum aktualisiert this.props.foooder this.props.bargeändert, CustomComponentRowda das unveränderliche Objekt ein anderes als das vorherige ist.

SudoPlz
quelle
2
Ich habe es endlich verstanden extraData! danke für den link zum VirtualisedListcode!
Tushar Koul
Hallo, @ SudoPiz Ich möchte Flatlist nach dem Löschen des letzten Elements neu rendern, kann diese Q stackoverflow.com/questions/58780167/…
Oliver D
6

Ich habe gerade herausgefunden, dass, wenn wir möchten, dass die FlatList die Datenänderung außerhalb der Daten-Requisite kennt, wir sie auf extraData setzen müssen, also mache ich das jetzt so:

<FlatList data={...} extraData={this.state} .../>

Siehe: https://facebook.github.io/react-native/docs/flatlist#extradata

Mahdi Bashirpour
quelle
1
Die beste Implementierung ... Ich habe es vorgezogen, sie als die gleiche wie die Daten-Requisite festzulegen, damit sie nicht aktualisiert wird, wenn sich etwas im Status ändert, aber dies ist bei weitem die EINFACHSTE Implementierung. Vielen Dank!
Robert Kehoe
Hallo, @MahdiBashirpour Ich möchte Flatlist nach dem Löschen des letzten Elements neu rendern, kann diese Q stackoverflow.com/questions/58780167/…
Oliver D
4

Wenn Sie einen Button haben, können Sie die Daten mit einem setState in der onPress aktualisieren. SetState rendert dann Ihre FlatList neu.

WilliamC
quelle
2
In meinem berührbaren Highlight befindet sich ein setState. Der setState funktioniert einwandfrei, aber die Flatlist zeigt keine Aktualisierung des Statuswerts
shalonteoh
Die Werte in Ihrer FlastList werden nicht aktualisiert, da Sie die Datenquelle nicht direkt aktualisieren. this.state.data wird mit der FlatList gerendert, aber in onPress aktualisieren Sie nur this.state.value.
WilliamC
Entschuldigung, mein Fehler, Frage Tippfehler. sollte this.state.data [index] .value sein
shalonteoh
3

Nach langem Suchen und Suchen nach einer echten Antwort habe ich endlich die Antwort bekommen, die ich für die beste halte:

       <FlatList
      data={this.state.data}
      renderItem={this.renderItem}
      ListHeaderComponent={this.renderHeader}
      ListFooterComponent={this.renderFooter}
      ItemSeparatorComponent={this.renderSeparator}
      refreshing={this.state.refreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={1}
      extraData={this.state.data}
      removeClippedSubviews={true}
      **keyExtractor={ (item, index) => index }**
              />
    .....

Mein Hauptproblem war (KeyExtractor), ich habe es nicht so benutzt. funktioniert nicht: keyExtractor = {(item) => item.ID} Nachdem ich dies geändert habe, hat es wie ein Zauber funktioniert. Ich hoffe, das hilft jemandem.

ramin azadi
quelle
Können Sie den Wert this.state.refreshingund die Funktion handleRefreshangeben?
DevAS
1

Ich habe dieses Problem durch Hinzufügen gelöst. extraData={this.state}Bitte überprüfen Sie den Code unten für weitere Details

render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.arr}
          extraData={this.state}
          renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
        />
      </View>
    );
  }
Nawaab Saab
quelle
1

Nur eine Erweiterung der vorherigen Antworten hier. Zwei Teile, um sicherzustellen, dass Sie extraData hinzufügen und dass Ihr keyExtractor eindeutig ist. Wenn Ihr keyExtractor konstant ist, wird kein erneuter Rendern ausgelöst.

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>
Nicholas Kuhne
quelle
0

Ich habe ersetzt FlatListmit SectionListund es ist Updates richtig auf Statusänderung.

<SectionList
  keyExtractor={(item) => item.entry.entryId} 
  sections={section}
  renderItem={this.renderEntries.bind(this)}
  renderSectionHeader={() => null}
/>

Das einzige, was Sie beachten müssen, ist sectiondie unterschiedliche Struktur:

const section = [{
  id: 0,
  data: this.state.data,
}]
Jamland
quelle
0

Für mich war der Trick extraData und ein weiterer Drilldown in die Item-Komponente

state = {
  uniqueValue: 0
}

<FlatList
  keyExtractor={(item, index) => item + index}
  data={this.props.photos}
  renderItem={this.renderItem}
  ItemSeparatorComponent={this.renderSeparator}
/>

renderItem = (item) => {
  if(item.item.selected) {
    return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
  }
  return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}

itemPressed (item) {
  this.props.photos.map((img, i) => {
    if(i === item.index) {
      if(img['selected') {
        delete img.selected;
      } else {
        img['selected'] = true;
      }
      this.setState({ uniqueValue: this.state.uniqueValue +1 });
    }
  }
}
Blenden
quelle
0

Fügen Sie Variablen, die durch Ihre Interaktion geändert werden, unter ein extraData

Sie können kreativ sein.

Zum Beispiel, wenn Sie es mit einer Änderungsliste mit Kontrollkästchen zu tun haben.

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  
Goodhyun
quelle
0

Wenn die FlatList wissen soll, dass die Daten sowohl die Requisite als auch den Status ändern , können wir ein Objekt erstellen , das sowohl auf die Requisite als auch auf den Status verweist, und die Flatlist aktualisieren.

const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>

Dokumente: https://facebook.github.io/react-native/docs/flatlist#extradata

Yogaraj Saravanan
quelle
0

In der React-Native-Flatlist sind sie eine Eigenschaft, die als extraData bezeichnet wird. Fügen Sie die folgende Zeile zu Ihrer Flatlist hinzu.

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />
Ravi
quelle
0

In diesem Beispiel ändern Sie einfach die Variable, um ein erneutes Rendern zu erzwingen machine

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])
Bill Zelenko
quelle
-1

Benutz einfach:

onRefresh={true}

in Ihrer flatListKomponente.

Taha Khozooie
quelle
1
Dies führt zu einem Fehler. Sie müssen dann refreshingprop
mahmoudafer
-1

Die extraData von Flatlist funktionierten nicht für mich und ich benutzte zufällig eine Requisite von Redux. Dies klang ähnlich wie in den Kommentaren in der Antwort von ED209. Ich habe setState manuell aufgerufen, als ich die Requisite erhalten habe.

componentWillReceiveProps(nextProps: StateProps) {
    if (this.props.yourProp != null && nextProps.yourProp) {
        this.setState({ yourState: processProp(nextProps.yourProp) });
    }
}


<FlatList
  data={this.state.yourState}
  extraData={this.state.yourState}
/>

Für diejenigen unter Ihnen, die> React 17 verwenden, verwenden Sie getDerivedStateFromProps

Herr Lee
quelle