Die Arbeit mit Daten in React ist relativ einfach, da React dafür konzipiert ist, Daten als State zu behandeln. Der Aufwand beginnt, wenn die Menge der zu verarbeitenden Daten gigantisch wird. Angenommen, Sie müssen einen Datensatz mit 500-1.000 Einträgen bearbeiten. Dies kann zu massiven Ladevorgängen und Leistungsproblemen führen. Nun werden wir uns ansehen, wie wir virtualisierte Listen in React verwenden können, um eine lange Datenliste nahtlos in Ihrer Anwendung darzustellen.
Wir werden die React Virtualized Komponente verwenden, um das zu erreichen, was wir brauchen. Sie ermöglicht es uns, große Datensätze zu verarbeiten, sie bei Bedarf zu verarbeiten und sie mit wenig bis gar keiner Ruckelei darzustellen.
Das Setup
React Virtualized hat bereits eine detaillierte Anleitung zur Einrichtung und Inbetriebnahme, daher schauen Sie sich das Repository an, um loszulegen.
Wir benötigen Daten zum Arbeiten, also richten wir eine Funktion ein, die faker verwendet, um einen großen Datensatz zu erstellen.
function createRecord(count) {
let records = [];
for (let i = 0; i < count; i++) {
records.push({
username: faker.internet.userName(),
email: faker.internet.email()
});
}
return records;
}
Als nächstes übergeben wir die Anzahl der zu erstellenden Datensätze, wie folgt:
const records = createRecord(1000);
Alles klar, jetzt haben wir, was wir brauchen, um mit der Darstellung einer Liste dieser Datensätze zu beginnen!
Erstellen einer virtualisierten Liste
Hier ist die Liste, die wir erstellen wollen, ohne Styling. Wir könnten einige der vorhandenen Präsentationsstile der Bibliothek nutzen, indem wir die mitgelieferte CSS-Datei importieren, aber wir lassen das in diesem Beitrag weg.
Siehe den Pen React Virtualized 1 von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.
Führen Sie diese Demo noch einmal aus. Unglaublich schnell, oder?
Sie fragen sich vielleicht, was React Virtualized hinter den Kulissen tut, um das zu ermöglichen. Es stellt sich heraus, dass es eine Menge verrückter und cooler Größenbestimmungen, Positionierungen, Transformationen und Übergänge sind, die es den Einträgen ermöglichen, in und aus dem Sichtbereich zu scrollen. Die Daten sind bereits vorhanden und gerendert. React Virtualized erstellt einen Fensterrahmen, der es den Einträgen ermöglicht, beim Scrollen durch den Benutzer ein- und auszublenden.
Um eine virtualisierte Liste in React Virtualized zu rendern, verwenden wir seine List Komponente, die intern eine Grid Komponente verwendet, um die Liste zu rendern.
Zuerst beginnen wir mit der Einrichtung von rowRenderer, der für die Anzeige einer einzelnen Zeile zuständig ist und einen Index festlegt, der jedem Datensatz eine ID zuweist.
rowRenderer = ({ index, isScrolling, key, style }) => {
return (
<div key={key} style={style}>
<div>{this.props.data[index].username}</div>
<div>{this.props.data[index].email}</div>
</div>
);
};
Wie Sie sehen können, gibt dies einen einzelnen div-Knoten zurück, der zwei weitere divs enthält: einen für den Benutzernamen und einen für die E-Mail. Sie wissen schon, ein gängiges Listenmuster zur Anzeige von Benutzern.
rowRenderer akzeptiert mehrere Parameter. Hier sind sie und was jeder von ihnen tut:
index: Die numerische ID eines Datensatzes.isScrolling: Gibt an, ob gerade imList-Komponente gescrollt wird.isVisible: Bestimmt, ob eine Zeile sichtbar oder außerhalb des Sichtbereichs ist.key: Die Position des Datensatzes im Array.parent: Definiert, ob die Liste ein Elternteil oder ein Kind einer anderen Liste ist.style: Ein Style-Objekt zur Positionierung der Zeile.
Nachdem wir nun mehr über die Funktion rowRenderer wissen, wollen wir sie in der List-Komponente verwenden.
<List
rowCount={this.props.data.length}
width={width}
height={height}
rowHeight={rowHeight}
rowRenderer={this.rowRenderer}
overscanRowCount={3}
/>
Sie haben vielleicht ein paar neue Parameter bemerkt. Hier ist, was sie sind:
rowCount: Dies nimmt die Anzahl der Zeilen in einer Liste entgegen, die wir übergeben, um die Länge unserer Liste zu berechnen.width: Die Breite der Liste.height: Die Höhe der Liste.rowHeight: Dies kann eine Zahl oder eine Funktion sein, die die Zeilenhöhe basierend auf ihrem Index zurückgibt.rowRenderer: Dies ist für die Darstellung der Zeile verantwortlich. Die Liste soll nicht direkt übergeben werden, daher übergeben wir die FunktionrowRenderer, die wir in diesem Tutorial erstellt haben.overscanRowCount: Dies wird verwendet, um zusätzliche Zeilen in der Scrollrichtung des Benutzers zu rendern. Es verringert die Wahrscheinlichkeit, dass der Benutzer schneller scrollt, als der virtualisierte Inhalt gerendert wird.
Am Ende sollte Ihr Code etwa so aussehen:
const { List } = ReactVirtualized
...
const height = 700;
const rowHeight = 40;
const width = 800;
class App extends React.Component {
rowRenderer = ({ index, isScrolling, key, style }) => {
return (
<div key={key} style={style}>
<div>{this.props.data[index].username}</div>
<div>{this.props.data[index].email}</div>
</div>
);
};
render() {
return (
<div>
<h2>Details</h2>
<List
rowCount={this.props.data.length}
width={width}
height={height}
rowHeight={rowHeight}
rowRenderer={this.rowRenderer}
overscanRowCount={3}
/>
</div>
);
}
}
Cell measurer
Laut Dokumentation ist ein Cell Measurer eine Higher-Order Component, die zum temporären Rendern einer Liste verwendet wird. Sie ist für den Benutzer zu diesem Zeitpunkt noch nicht sichtbar, aber die Daten sind vorhanden und bereit zur Anzeige.
Warum sollten Sie sich dafür interessieren? Der beliebteste Anwendungsfall ist eine Situation, in der der Wert Ihrer rowHeight dynamisch ist. React Virtualized kann die Höhe der Zeile beim Rendern ermitteln und diese Höhe dann cachen, sodass nicht mehr berechnet werden muss, wenn Daten aus dem Sichtbereich gescrollt werden – sie hat immer die richtige Höhe, unabhängig vom Inhalt!
Zuerst erstellen wir unseren cache, was im Konstruktor unserer Komponente mit CellMeasurerCache geschehen kann.
constructor() {
super()
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 100
})
}
Wir nutzen den Cache, wenn wir die List-Komponente einrichten;
<List
rowCount={this.props.data.length}
width={rowWidth}
height={listHeight}
deferredMeasurementCache={this.cache}
rowHeight={this.cache.rowHeight}
rowRenderer={this.renderRow}
overscanRowCount={3}
/>
Der an deferredMeasurementCache übergebene Wert wird verwendet, um die Daten temporär zu rendern, und dann – sobald der berechnete Wert für rowHeight eintrifft – werden zusätzliche Zeilen so eingefügt, als wären sie schon immer da gewesen.
Als Nächstes werden wir die CellMeasurer-Komponente von React Virtualized anstelle des div-Elements, das wir ursprünglich als Platzhalter eingerichtet haben, in unserer rowRenderer-Funktion verwenden.
rowRenderer = ({ index, parent, key, style }) => {
return (
<CellMeasurer
key={key}
cache={this.cache}
parent={parent}
columnIndex={0}
rowIndex={index}
>
<div style={style}>
<div>{this.props.data[index].username}</div>
<div>{this.props.data[index].email}</div>
</div>
</CellMeasurer>
);
};
Jetzt sind die Daten abrufbar, gecacht und bereit, nach Belieben im virtuellen Fenster angezeigt zu werden!
Virtualisierte Tabelle
Ja, der Hauptzweck dieses Beitrags ist die Behandlung von Listen, aber was, wenn wir stattdessen Daten in einer Tabelle darstellen wollen? React Virtualized hat auch dafür eine Lösung. In diesem Fall werden wir die Table- und Column-Komponenten verwenden, die in React Virtualized integriert sind.
Hier ist, wie wir diese Komponenten in unserer primären App-Komponente verwenden würden:
class App extends React.Component {
render() {
return (
<div>
<h2>Details</h2>
<Table
width={500}
height={300}
headerHeight={20}
rowHeight={40}
rowCount={this.props.data.length}
rowGetter={({ index }) => this.props.data[index]}
>
<Column
label='Username'
dataKey='username'
width={100}
/>
<Column
width={200}
label='Email'
dataKey='email'
/>
</Table>
</div>
);
}
}
Die Table-Komponente akzeptiert die folgenden Parameter:
width: Die Breite der Tabelle.height: Die Höhe der Tabelle.headerHeight: Die Höhe des Tabellenkopfes.rowHeight: Die Höhe einer Zeile, gegeben ihren Index.rowCount: Dies ist die anfängliche Anzahl von Zeilen, die wir in der Tabelle haben möchten. Es ist dasselbe wie die Art und Weise, wie wir die Anzahl der Datensätze definiert haben, mit denen wir imList-Komponentenbeispiel beginnen wollten.rowGetter: Dies gibt die Daten einer bestimmten Zeile anhand ihres Index zurück.
Wenn Sie sich die Column-Komponente ansehen, werden Sie feststellen, dass wir einen dataKey-Parameter verwendet haben. Dieser übergibt die Daten für jede Spalte, die wir in dataKey aufgerufen haben, welche eine eindeutige Kennung für diese Daten erhält. Denken Sie daran, dass wir in der Funktion, in der wir unsere zufälligen Daten erstellen, zwei Schlüssel verwenden: username und email. Deshalb haben wir den dataKey einer Spalte auf username und den der anderen auf email gesetzt.
Zusammenfassend
Hoffentlich gibt Ihnen dieser Leitfaden eine gute Vorstellung davon, wozu React Virtualized fähig ist, wie es die Darstellung großer Datensätze in Listen und Tabellen superschnell machen kann und wie Sie es in einem Projekt einsetzen können.
Wir haben hier nur an der Oberfläche gekratzt. Die Bibliothek kann viele weitere Anwendungsfälle bewältigen, wie z. B. das Generieren von Platzhaltern für die Datensätze beim Scrollen, eine Infinite Loader Komponente zum Abrufen und Cachen von Daten in Echtzeit, eine Methode zum Navigieren mit den Pfeiltasten durch die Daten und eine elegante Grid und Masonry Layouts, die wir hier noch nicht einmal behandelt haben.
Das sollte Ihnen viel zum Ausprobieren geben!
Außerdem wird das Paket sehr gut gepflegt. Tatsächlich können Sie der Slack-Gruppe beitreten, um über das Projekt auf dem Laufenden zu bleiben, dazu beizutragen und sich generell mit anderen Leuten zu vernetzen.
Es ist auch erwähnenswert, dass React Virtualized einen eigenen Tag auf StackOverflow hat und dies eine gute Ressource sein kann, um Fragen zu finden, die andere Leute bereits gestellt haben, oder um Ihre eigenen Fragen zu stellen.
Oh, und wenn Sie React Virtualized in einem Projekt eingesetzt haben, würden wir es gerne wissen! Teilen Sie es uns in den Kommentaren mit einigen Hinweisen, wie Sie vorgegangen sind oder was Sie daraus gelernt haben.
Es lohnt sich vielleicht zu erwähnen, dass der Autor von React Virtualized später React Window mit den aus React Virtualized gewonnenen Erkenntnissen erstellt hat. Wenn Sie also noch keines von beiden verwenden, sollten Sie wahrscheinlich direkt zu React Window wechseln.
Danke Gabriel für die Erwähnung, davon wusste ich nichts, bevor ich diesen Artikel geschrieben habe.
Ja!, das ist eine leichtgewichtige Bibliothek von react-virtualized.
Danke Gabriel für die Erwähnung von React Window. Dieses hier ist in seiner Readme großartig: „Das Hinzufügen einer react-virtualized Liste zu einem CRA-Projekt erhöht die (gzippte) Build-Größe um ~33,5 KB. Das Hinzufügen einer react-window Liste zu einem CRA-Projekt erhöht die (gzippte) Build-Größe um <2 KB.“
Gibt es ein Beispiel, das Datenzeilen auflistet, die aus verschiedenen Komponenten bestehen? Ich bin neugierig, wie schnell diese Komponente in einem solchen Szenario laden wird, da eine Textliste immer schnell lädt, verglichen mit einer komplexeren Liste aus zusammengesetzten Komponenten mit Avataren, Bildern und dergleichen.