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

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.


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

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.


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


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.


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.


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

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>

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,
}]

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

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>  

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


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

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

-1

Benutz einfach:

onRefresh={true}

in Ihrer flatListKomponente.


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.