React-native: Verwirrung über `rowHasChanged` und ListView-Rendering

Erstellt am 4. Feb. 2016  ·  3Kommentare  ·  Quelle: facebook/react-native

Hallo zusammen,

Während ich an einigen Leistungsverbesserungen arbeitete, fand ich heraus, dass rowHasChanged in keiner unserer Listen genannt wurde. Diese Listen sind endlos scrollende Listen, was bedeutet, dass, wenn Sie das Ende erreichen, mehr Elemente zum Anzeigen abgerufen und dann in die Liste abgelegt werden.

Es scheint, als würden alle Einträge in der Liste aktualisiert, wenn wir den Inhalt der DataSource ändern. Wir haben zwar ein shouldComponentUpdate für alle Zeilen, aber wie ich rowHasChanged verstanden habe, müssten diese Zeilen nicht erneut gerendert werden.

Ich habe ein einfaches Beispiel erstellt, das zeigt, wie wir Elemente an die Liste anhängen: https://gist.github.com/janmonschke/c9c84b6050683da0c64f

Was wir grundsätzlich tun ist:

constructor() {
  // (...)
  this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => {
    console.log('rowHasChanged');
    return r1 !== r2;
  }});
  // (...)
}

onEndReached = () => {
  // append data to the end
  setData = [...setData, ...genRandomSet()];
  this.setState({
    dataSource: this.ds.cloneWithRows(setData)
  });
  console.log('onEndReached');
};

render() {
  return (
    <ListView
      dataSource={this.state.dataSource}
      renderRow={this.renderRow}
      onEndReached={this.onEndReached}
    />
  );
}

Aber rowHasChanged wird nie protokolliert.

Benutze ich es irgendwie falsch? Gibt es bessere Möglichkeiten, an eine ListView anzuhängen?

Gleiches Verhalten in 0.18.0 und 0.19.0

Locked

Hilfreichster Kommentar

Okay, die Lösung gefunden in: http://stackoverflow.com/a/33871118.

Anscheinend ist es wichtig, von der richtigen DataSource-Instanz zu klonen;)

Der Code aus dem Kern sollte also lauten:

  setData = [...setData, ...genRandomSet()];
  this.setState({
    dataSource: this.state.dataSource.cloneWithRows(setData)
  });

Dies scheint ein Fehler zu sein, der sich leicht in Ihre Codebasis einschleicht. Ich frage mich, ob die korrekte Verwendung von DataSource in der Dokumentation stärker betont werden sollte.

Alle 3 Kommentare

Hey Janmonschke, danke, dass du dieses Problem gemeldet hast!

Wie Sie wahrscheinlich schon gehört haben, wird React Native immer beliebter, und die Wahrheit ist, dass wir von der Aktivität, die es umgibt, ein wenig überwältigt werden. Es gibt einfach zu viele Probleme, als dass wir sie richtig handhaben könnten.

  • Wenn Sie nicht wissen, wie Sie etwas tun sollen oder etwas nicht wie erwartet funktioniert, aber nicht sicher ist, ob es sich um einen Fehler handelt, fragen Sie bitte auf StackOverflow mit dem Tag react-native oder für weitere Echtzeit-Interaktionen auf Discord im #react-nativer Kanal.
  • Wenn dies eine Funktionsanfrage oder ein Fehler ist, den Sie beheben möchten, melden Sie dies bitte auf Product Pains . Es verfügt über eine Ranking-Funktion, mit der wir uns auf die wichtigsten Probleme der Community konzentrieren können.
  • Wir begrüßen klare Themen und PRs, die für eine eingehende Diskussion bereit sind. Bitte stelle gegebenenfalls Screenshots zur Verfügung und erwähne immer die Version von React Native, die du verwendest. Vielen Dank für Ihre Beiträge!

Okay, die Lösung gefunden in: http://stackoverflow.com/a/33871118.

Anscheinend ist es wichtig, von der richtigen DataSource-Instanz zu klonen;)

Der Code aus dem Kern sollte also lauten:

  setData = [...setData, ...genRandomSet()];
  this.setState({
    dataSource: this.state.dataSource.cloneWithRows(setData)
  });

Dies scheint ein Fehler zu sein, der sich leicht in Ihre Codebasis einschleicht. Ich frage mich, ob die korrekte Verwendung von DataSource in der Dokumentation stärker betont werden sollte.

Danke @janmonschke! Ich stimme zu, ich hatte eine Reihe von Ansichten, die ständig neu gerendert wurden, und ich konnte nicht herausfinden, warum das passierte und warum die Funktion rowHasChanged nie aufgerufen wurde. 👊

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen