SkillGridInformatik durch Machen lernen

Rendering: wie aus Änderung Pixel werden

Was ein erneutes Rendering wirklich ist, warum die Schnittstelle eine Funktion des Zustands ist, warum key in Listen entscheidet, welche Zeile der Browser wiederverwendet, und warum Messen besser ist als Raten.

14 Min. · 45 XP

Ein Zähler, der funktioniert, wirkt etwa einen Tag lang wie Magie. Dann fügst du eine Liste auf der Seite hinzu, die Zeilen verhalten sich seltsam, und die Magie wird zur Frage: Was genau passiert zwischen dem Klick und den neuen Pixeln?

Zuerst klären wir das Wort. Neuladen bedeutet, dass der Browser die Seite wegwirft und alles erneut vom Server anfordert: ein neues Dokument, neue Elemente, und jeder Zustand, den du hattest, ist weg. Ein erneutes Rendering ist nichts dergleichen. Die Seite bleibt, der Browser-Tab bleibt, und die Komponentenfunktionen laufen erneut, um eine frische Beschreibung der Schnittstelle zu erzeugen. Niemand spricht mit dem Server, außer dein Code fragt nach Daten.

UserAppDOMreloadF5a completely new treere-renderclickonly the text that changedthe same tree, one detail updated

Genau deshalb schreibt man die Schnittstelle als Funktion des Zustands. Du beschreibst nicht den Übergang vom alten zum neuen Bildschirm. Du beschreibst, wie der Bildschirm für die aktuellen Daten aussehen soll, und überlässt es dem Framework, den Unterschied herauszufinden.

function Total({ items }) {
  const sum = items.reduce((acc, item) => acc + item.price, 0);
  return <p>{sum}</p>;
}

const view = <Total items={cart} />;Bei gleichem Warenkorb liefert diese Funktion immer dieselbe Summe.

Jetzt der klassische Fehler. Du zeichnest eine Liste aus Daten, und jede Zeile bekommt einen stabilen key, der den Eintrag kennzeichnet und nicht seine Position.

function Rows({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

items.map((item) => <li>{item.name}</li>);Die erste Version gibt dem Framework eine stabile Identität pro Zeile. Die zweite gibt ihm nichts.

Der key ist die Art, wie das Framework erkennt, dass diese Zeile auf dem Bildschirm derselbe Eintrag ist wie jene in den neuen Daten. Ohne keys fällt es auf die Position zurück: Zeile eins ist Zeile eins, Zeile zwei ist Zeile zwei. Füge oben in einer Liste aus Textfeldern einen Eintrag ein, und die Werte scheinen eine Zeile nach unten zu springen, weil der Browser das erste Feld behalten und nur die Beschriftung darüber geändert hat. Die Daten waren nie falsch. Die Zeilen wurden nur nie den richtigen Einträgen zugeordnet.

Wenn das erneute Rendering einer Komponente bedeutet, die Funktion noch einmal auszuführen, warum ist das dann nicht furchtbar langsam? Weil es das meistens nicht ist. Ein Tastendruck führt vielleicht eine Handvoll kleiner Funktionen aus, die ein paar hundert einfache Objekte bauen, und das ist viel billiger, als wenn der Browser ein Bild zeichnet. Es ist bezahlbar, was vor zwanzig Jahren einfach nicht ging, und moderne Anwendungen bauen auf dieser Tatsache auf.

Genau deshalb ist der ehrliche Rat zur Geschwindigkeit langweilig: Messe, bevor du optimierst. Eine Seite kann sich tausendmal pro Sekunde neu rendern und sich sofort anfühlen, während ein einziger falsch dimensionierter Bild-Baustein sie kaputt wirken lässt. Zu raten, welcher Teil langsam ist, ist das unzuverlässigste Werkzeug überhaupt; der Browser bringt schon Profiler mit, die es dir einfach sagen.

Praxis

  1. Ein Zähler aktualisiert seine Zahl sofort, die Adresse in der Adressleiste ändert sich nicht, und der Rest der Seite behält seine Scrollposition. Was ist passiert?

    Hinweise
    • Achte auf die Adressleiste und die Scrollposition: Beim Neuladen werden sie zerstört und neu aufgebaut, beim erneuten Rendering nicht.
    • Beim erneuten Rendering laufen dieselben Komponentenfunktionen noch einmal durch. Die Seite wird nicht erneut vom Server angefordert.
  2. Ein Suchfeld holt die Ergebnisse einmal von einer API und filtert sie danach bei jedem Tastendruck lokal. Bring die Schritte in die richtige Reihenfolge.

    1. 1Die Komponente berechnet, welche Ergebnisse zum aktuellen Text passen
    2. 2Sie gibt die Elemente für die passenden Zeilen zurück, jede mit einem stabilen key
    3. 3Die zurückgegebene Liste wird als Zustand behalten, also übersteht sie die nächsten Durchläufe
    4. 4Die Komponente fragt den Server einmal nach der Liste
    5. 5Das Framework aktualisiert nur die Zeilen, deren Inhalt sich geändert hat
    Hinweise
    • Nichts kann berechnet werden, bevor die Daten geholt wurden, und nichts kann gezeichnet werden, bevor es berechnet wurde.
    • Der Knopf ist nicht der Wert. Der Klick fordert die Änderung nur an; die Änderung selbst passiert im nächsten Schritt.
  3. Ordne jede Situation der ehrlichen Erklärung zu, was wirklich passiert.

    Hinweise
    • Die eine Spalte handelt von einem Wert, der sich geändert hat, die andere davon, was der Browser damit macht.
    • Überlege, was auf den Zählerknopf zutrifft und was auf eine Seite, die neu geladen wird.