667 Stimmen

ReactJS - Wird "render" jedes Mal aufgerufen, wenn "setState" aufgerufen wird?

Rendert React bei jedem Aufruf von setState() alle Komponenten und Unterkomponenten neu?

Wenn ja, warum? Ich dachte, die Idee war, dass React nur so wenig wie möglich rendert - wenn sich der Zustand ändert.

In folgendem einfachen Beispiel rendern beide Klassen erneut, wenn der Text angeklickt wird, obwohl sich der Zustand bei aufeinanderfolgenden Klicks nicht ändert, da der onClick-Handler immer den state auf den gleichen Wert setzt:

this.setState({'test':'me'});

Ich hätte erwartet, dass ein Rendern nur dann stattfindet, wenn sich die Daten des state geändert haben.

Hier ist der Code des Beispiels, als JS Fiddle, und eingebetteter Ausschnitt:

var TimeInChild = React.createClass({
    render: function() {
        var t = new Date().getTime();

        return (
            Zeit im Kind:{t}
        );
    }
});

var Main = React.createClass({
    onTest: function() {
        this.setState({'test':'me'});
    },

    render: function() {
        var currentTime = new Date().getTime();

        return (

            Zeit im Hauptbereich:{currentTime}
            Klicken Sie auf mich, um die Zeit zu aktualisieren

        );
    }
});

ReactDOM.render(

673voto

Petr Punkte 7115

Rendert React bei jedem Aufruf von setState alle Komponenten und Unterkomponenten neu?

Standardmäßig - ja.

Es gibt eine Methode boolean shouldComponentUpdate(object nextProps, object nextState), jede Komponente hat diese Methode und ist dafür verantwortlich zu bestimmen, ob "soll die Komponente aktualisiert werden (die render Funktion ausgeführt werden)?" jedes Mal, wenn Sie den state ändern oder neue props von der übergeordneten Komponente übergeben.

Sie können Ihre eigene Implementierung der Methode shouldComponentUpdate für Ihre Komponente schreiben, aber die Standardimplementierung gibt immer true zurück - was bedeutet, dass die render Funktion immer wieder ausgeführt wird.

Zitat aus der offiziellen Dokumentation http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate

Standardmäßig gibt shouldComponentUpdate immer true zurück, um subtile Fehler zu verhindern, wenn der Zustand an Ort und Stelle mutiert wird, aber wenn Sie immer darauf achten, den Zustand als unveränderlich zu behandeln und nur aus props und Zustand in render() zu lesen, können Sie shouldComponentUpdate mit einer Implementierung überschreiben, die die alten props und Zustand mit ihren Ersatzwerten vergleicht.

Nächster Teil Ihrer Frage:

Wenn ja, warum? Ich dachte, die Idee war, dass React nur so wenig wie nötig rendern würde - wenn sich der Zustand ändert.

Es gibt zwei Schritte von dem, was wir "rendern" nennen können:

  1. Virtual DOM Rendering: Wenn die render Methode aufgerufen wird, gibt sie eine neue Virtual DOM Struktur der Komponente zurück. Wie ich zuvor erwähnt habe, wird diese render Methode immer aufgerufen, wenn Sie setState() aufrufen, weil shouldComponentUpdate standardmäßig immer true zurückgibt. Also, standardmäßig gibt es hier keine Optimierung in React.

  2. Native DOM Rendering: React ändert nur die echten DOM-Knoten in Ihrem Browser, wenn sie im Virtual DOM geändert wurden und nur so wenig wie nötig - das ist das großartige Feature von React, das die Mutation des echten DOM optimiert und React schnell macht.

138voto

tungd Punkte 14027

Nein, React rendert nicht alles, wenn sich der Zustand ändert.

  • Immer wenn eine Komponente dirty ist (ihr Zustand sich geändert hat), wird diese Komponente und ihre Kinder neu gerendert. Dies geschieht zum Teil, um so wenig wie möglich neu zu rendern. Die einzige Zeit, in der render nicht aufgerufen wird, ist wenn ein Zweig zu einem anderen Root verschoben wird, wo theoretisch nichts neu gerendert werden muss. In deinem Beispiel wird TimeInChild als Unterkomponente von Main betrachtet, also wird auch sie neu gerendert, wenn sich der Zustand von Main ändert.

  • React vergleicht keine Zustandsdaten. Wenn setState aufgerufen wird, markiert es die Komponente als dirty (was bedeutet, dass sie neu gerendert werden muss). Wichtig ist zu beachten, dass obwohl die render-Methode der Komponente aufgerufen wird, der echte DOM nur aktualisiert wird, wenn die Ausgabe sich von dem aktuellen DOM-Baum unterscheidet (auch bekannt als Differenzierung zwischen dem Virtual DOM-Baum und dem DOM-Baum des Dokuments). In deinem Beispiel, obwohl sich die state-Daten nicht geändert haben, hat sich die Zeit der letzten Änderung geändert, was den Virtual DOM vom Dokument DOM unterscheidet, daher wird das HTML aktualisiert.

15voto

lakmal_sathyajith Punkte 218

Ja. Es ruft die Methode render() jedes Mal auf, wenn wir setState aufrufen, außer wenn shouldComponentUpdate false zurückgibt.

12voto

lifeisfoo Punkte 13648

React 18 und darüber hinaus

Ab React 18 werden alle Statusupdates automatisch gruppiert. Auf diese Weise gruppiert React mehrere Statusupdates zu einem einzigen Neuzeichnen für bessere Leistung.

Also, wenn du deinen Status aktualisierst, versucht React immer, diese Updates in einer Gruppenaktualisierung zu bündeln, wodurch weniger render als setState-Aufrufe verursacht werden. Das Verhalten ist dasselbe bei Verwendung von Hooks.

Du kannst die sehr ausführliche Erklärung in der Automatischen Gruppierung für React 18-Ankündigung lesen.

React 17 und darunter

In React 17 und darunter werden nur Updates innerhalb von React-Ereignisbehandlern gruppiert. Updates, die von Promises, setTimeout, nativen Ereignisbehandlern oder anderen Ereignissen ausgelöst werden, werden standardmäßig nicht von React gruppiert.

11voto

Brad Parks Punkte 59613

Auch wenn es in vielen der anderen Antworten hier erwähnt wird, sollte das Komponente entweder:

  • shouldComponentUpdate implementieren, um nur zu rendern, wenn sich der Status oder die Eigenschaften ändern

  • zu einer Erweiterung eines PureComponent wechseln, der bereits intern eine shouldComponentUpdate-Methode für flache Vergleiche implementiert.

Hier ist ein Beispiel, das shouldComponentUpdate verwendet, das nur für diesen einfachen Anwendungsfall und Demonstrationszwecke funktioniert. Wenn dies verwendet wird, wird die Komponente nicht mehr bei jedem Klick neu gerendert und wird gerendert, wenn sie zum ersten Mal angezeigt wird und nachdem sie einmal geklickt wurde.

var ZeitImKind = React.createClass({
    render: function() {
        var t = new Date().getTime();

        return (
            Zeit im Kind:{t}
        );
    }
});

var Haupt = React.createClass({
    onTest: function() {
        this.setState({'test':'me'});
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      if (this.state == null)
        return true;

      if (this.state.test == nextState.test)
        return false;

      return true;
  },

    render: function() {
        var aktuelleZeit = new Date().getTime();

        return (

            Zeit im Haupt:{aktuelleZeit}
            Klicke mich an, um die Zeit zu aktualisieren

        );
    }
});

ReactDOM.render(, document.body);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X