Rendering Lists Using React Virtualized

Avatar of Kingsley Silas
Kingsley Silas am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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 im List-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 Funktion rowRenderer, 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 im List-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.