Heim > Web-Frontend > js-Tutorial > Optimierung der Reaktionsleistung mit staatenlosen Komponenten

Optimierung der Reaktionsleistung mit staatenlosen Komponenten

Lisa Kudrow
Freigeben: 2025-02-16 11:35:08
Original
266 Leute haben es durchsucht

Optimizing React Performance with Stateless Components

Optimizing React Performance with Stateless Components

In diesem Artikel werden die staatenlosen Komponenten in React untersucht. Diese Art von Komponenten enthält keine Aufrufe this.state = { ... } und verarbeitet nur eingehende "Requisiten" und untergeordnete Komponenten.

Zusammenfassung der Schlüsselpunkte

  • Die zustandslose Komponente in React enthält keine this.state = { … } -Anrufe. Sie kümmern sich nur um eingehende "Requisiten" und Unterkomponenten, was es einfacher und einfacher aus einer Testperspektive zu analysieren kann.
  • Staurose Komponenten können in funktionale Komponenten umgewandelt werden, was eher wie reinem JavaScript ähnelt und weniger von dem verwendeten Framework abhängig ist.
  • Die Leistung staatenloser Komponenten kann durch Verwendung von React.PureComponent optimiert werden, das eine integrierte shouldComponentUpdate -Methode aufweist, die flache Vergleiche jeder Propitus ermöglicht.
  • Recompose ist eine Versorgungsbibliothek für Funktionskomponenten und erweiterte Komponenten in React. Es kann verwendet werden, um Funktionskomponenten ohne Wiederaufnahme zu rendern, wenn die Requisiten unverändert sind.
  • Staatelose Komponenten können die Leistung von React -Anwendungen erheblich verbessern, da sie ihren eigenen Zustand oder ihre Lebenszyklusmethoden nicht verwalten und so das Codevolumen und der Speicherverbrauch verringern. Sie haben jedoch auch einige Einschränkungen, z.

Grundlagen

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der Code wird normal ausgeführt. Es ist sehr einfach, aber es baut Beispiele auf.

Es sollte beachtet werden:

  • es ist auf Staurellos, ohne this.state = { ... }.
  • console.log wird verwendet, um seine Verwendung zu verstehen. Insbesondere bei der Durchführung der Leistungsoptimierung, wenn die Requisiten nicht tatsächlich geändert werden, muss unnötiges Wiederaufbau vermieden werden.
  • Der Event -Handler hier ist "Inline". Diese Syntax ist bequem, da sein Code nahe an den Elementen liegt, die sie verarbeitet, und diese Syntax bedeutet, dass Sie nichts .bind(this) tun müssen.
  • Die Verwendung einer solchen Inline -Funktion hat einen kleinen Leistungsverlust, da die Funktion jedes Mal erstellt werden muss, wenn sie wiedergegeben wird. Dies wird später detailliert sein.

Zeigen Sie die Komponente

an

Wir erkennen nun, dass die obige Komponente nicht nur staatenlos ist, sondern auch das, was Dan Abramov eine Anzeigekomponente nennt. Es ist nur ein Name, aber im Grunde ist es leicht, erzeugt HTML/DOM und behandelt keine staatlichen Daten.

So können wir es in eine Funktion machen! Dies fühlt sich nicht nur "cool" an, sondern macht es auch weniger schrecklich, weil es einfacher zu verstehen ist. Es empfängt Eingaben und gibt unabhängig von der Umgebung immer die gleiche Ausgabe zurück. Natürlich "Rückruf", weil eine der Requisiten eine aufrufbare Funktion ist.

Schreiben wir es neu:

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

es fühlt sich gut an, oder? Es fühlt sich wie reines JavaScript an, Sie können es schreiben, ohne über den Rahmen nachzudenken, den Sie verwenden.

Das Problem der kontinuierlichen Wiederholung

Angenommen, unsere Benutzerkomponente wird in einer Komponente verwendet, die den Status im Laufe der Zeit ändert. Der Staat wirkt sich jedoch nicht auf unsere Komponenten aus. Zum Beispiel wie folgt:

const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Führen Sie diesen Code aus und Sie werden feststellen, dass auch wenn sich nichts ändert, unsere Komponenten erneut gerendert werden! Dies ist jetzt kein großes Problem, aber in praktischen Anwendungen werden Komponenten in der Regel immer komplexer, und jede unnötige Wiederholung führt zu einer Verlangsamung der Website.

Wenn Sie react-addons-perf verwenden, um diese Anwendung jetzt zu debuggen, werden Sie sicher feststellen, dass die Zeit beim Rendern Users->User verschwendet wird. Hoppla! was zu tun? !

Es scheint, dass alles zeigt, dass wir shouldComponentUpdate verwenden müssen, um zu decken, wie React der Meinung ist, dass Requisiten unterschiedlich sind, und wir sind sicher, dass sie nicht unterschiedlich sind. Um einen React -Lebenszyklushaken hinzuzufügen, muss die Komponente eine Klasse sein. alas . Wir kehren also zur ursprünglichen klassenbasierten Implementierung zurück und fügen eine neue Lebenszyklus-Hook-Methode hinzu:

Zurück zur Klassenkomponente

import React, { Component } from 'react'

class Users extends Component {
  constructor(props) {
    super(props)
    this.state = {
      otherData: null,
      users: [{name: 'John Doe', highlighted: false}]
    }
  }

  async componentDidMount() {
    try {
      let response = await fetch('https://api.github.com')
      let data = await response.json()
      this.setState({otherData: data})
    } catch(err) {
      throw err
    }
  }

  toggleUserHighlight(user) {
    this.setState(prevState => ({
      users: prevState.users.map(u => {
        if (u.name === user.name) {
          u.highlighted = !u.highlighted
        }
        return u
      })
    }))
  }

  render() {
    return <div>
      <h1>Users</h1>
      {
        this.state.users.map(user => {
          return <User
            name={user.name}
            highlighted={user.highlighted}
            userSelected={() => {
              this.toggleUserHighlight(user)
            }}/>
         })
      }
    </div>
  }
}
Nach dem Login kopieren

achten Sie auf die neu hinzugefügte shouldComponentUpdate -Methode. Das ist ein bisschen hässlich. Wir können nicht nur Funktionen mehr verwenden, sondern müssen auch die möglicherweise geänderten Requisiten manuell auflisten. Dies beinhaltet eine mutige Annahme, dass sich die Function -Requisite nicht ändert. Dies ist unwahrscheinlich, aber es braucht Aufmerksamkeit. userSelected

Aber bitte beachten Sie, dass auch wenn die enthaltene App-Komponente erneut gerendert wird, dies nur einmal gerendert wird! Das ist also gut für die Leistung. Aber können wir es besser machen?

react.pureComponent

Seit React 15.3 gibt es eine neue Komponentenbasisklasse. Es heißt PureComponent und hat eine integrierte shouldComponentUpdate -Methode, die einen "flachen Vergleich" jeder Requisite macht. wunderbar! Wenn wir dies verwenden, können wir unsere benutzerdefinierte shouldComponentUpdate -Methode verwerfen, die bestimmte Requisiten auflisten muss.

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Versuchen Sie es und Sie werden enttäuscht sein. Es wird jedes Mal wiedergegeben. Warum? ! Die Antwort liegt daran, dass die userSelected -Funktion jedes Mal in der Methode der App nachgebildet wird. Dies bedeutet, dass eine basierte Komponente, wenn sie seine eigene render aufruft, PureComponent zurückgibt, da die Funktion immer anders ist, da sie jedes Mal erstellt wird. shouldComponentUpdate() true Normalerweise besteht die Lösung für dieses Problem darin, die Funktion in den Konstruktor zu binden, der die Komponente enthält. Wenn wir dies tun, müssen wir den Methodennamen 5 Mal (und 1 vorher) eingeben:

    (im Konstruktor)
  • this.userSelected = this.userSelected.bind(this)
  • (als Methodendefinition selbst)
  • userSelected() { ... }
  • (wo das Rendering der Benutzerkomponente definiert ist)
  • <User ... userSelected={this.userSelected} ... />
  • Ein weiteres Problem ist, dass, wie Sie sehen können, wenn die
-Methode tatsächlich ausgeführt wird, sie von einer Schließung abhängt. Insbesondere beruht es auf der Umfangsvariablen

des Iterators. userSelected this.state.users.map() zugegebenermaßen gibt es eine Lösung für dieses Problem, bei dem zuerst die user -Methode an

gebunden wird. Wenn die Methode aufgerufen wird (in einer untergeordneten Komponente), übergeben ) geh zurück. Hier ist eine solche Lösung.

userSelected this Um zu retten! user

Erstens überprüfen wir unsere Ziele:

  1. Das Schreiben funktionaler Komponenten fühlt sich besser an, weil sie Funktionen sind. Dies zeigt dem Code -Leser sofort mit, dass er keinen Zustand speichert. Sie sind aus Sicht der Unit -Test leicht zu argumentieren. Und sie fühlen sich prägnanter und eher wie reines JavaScript (und natürlich JSX).
  2. Wir sind zu faul, um alle an Kinderkomponenten übergebenen Methoden zu binden. Wenn die Methoden komplex sind, ist es natürlich besser, sie neu zu überarbeiten, anstatt sie dynamisch zu erstellen. Dynamische Erstellungsmethoden bedeuten, dass wir ihren Code direkt dort schreiben können, wo sie verwendet werden. Wir müssen sie nicht nennen, und wir haben sie auch nicht an drei verschiedenen Stellen erwähnt.
  3. Unterkomponenten sollten nur dann erneut gerendert werden, wenn sich die Props ändern. Dies mag für kleine und schnelle Komponenten nicht von Bedeutung sein, aber für praktische Anwendungen können bei vielen dieser Komponenten alle diese zusätzlichen Renderings CPU verschwenden, wenn vermieden werden kann.
(in der Tat ist unsere ideale Situation, dass die Komponente nur einmal gerendert wird. Warum kann dieses Problem für uns nicht reagieren? .)

gemäß der Dokumentation ist Recompose "eine Bibliothek von React -Dienstprogramm -Tools für Funktionskomponenten und erweiterte Komponenten. Stellen Sie sich dies als Lodash für React."

. In dieser Bibliothek gibt es eine Menge zu erforschen, aber jetzt möchten wir unsere Funktionskomponenten ohne Wiederholung durchführen, wenn sich die Requisiten nicht geändert haben. Wenn wir das erste Mal versuchten, sie mit recompose.pure in die Funktionskomponente umzuschreiben, sieht es so aus:

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Sie können feststellen, dass die Benutzerkomponente, wenn Sie diesen Code ausführen, weiterhin erneut rendern, wenn sich die Requisiten (

und

Tasten) nicht geändert haben. name highlighted Lassen Sie uns noch einen Schritt weiter gehen. Wir verwenden

nicht, aber wir verwenden

, eine Version von recompose.pure, aber Sie können den Requisitenschlüssel angeben, auf den Sie sich konzentrieren möchten: recompose.onlyUpdateForKeys recompose.pure

const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Nach dem Ausführen dieses Code werden Sie feststellen, dass er nur aktualisiert wird, wenn sich

oder

Requisiten ändern. Wenn die übergeordnete Komponente erneut gerendert wird, tut die Benutzerkomponente dies nicht. name highlighted Lange Live! Wir fanden Gold!

Diskussion

Fragen Sie sich zunächst, ob es sich lohnt, Ihre Komponentenleistung zu optimieren. Vielleicht ist das mehr als es wert ist. Ihre Komponenten sollten leicht sein, möglicherweise können Sie alle teuren Berechnungen aus den Komponenten verschieben und in externe unvergessliche Funktionen verschieben, oder Sie können Ihre Komponenten neu organisieren, damit einige Daten bei der Verwendung keine Verschwendung von Rendering -Komponenten sein können. In diesem Beispiel möchten Sie beispielsweise die Benutzerkomponente möglicherweise nicht vornehmen.

Der Code auf die bequemste Weise für Sie schreiben, dann ist es keine schlechte Lösung, Ihr Programm zu starten und zu iterieren, damit er besser funktioniert. In diesem Beispiel müssen Sie die Funktionskomponente aus:

definieren, um die Leistung zu verbessern:
import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

… geändert in…
const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

shallowEqual Idealerweise ist die beste Lösung ein neuer Patch aus React, anstatt einen Weg zu zeigen, um das Problem zu umgehen, was eine enorme Verbesserung gegenüber

zum "automatischen" identifizieren, das eingehende und vergleichen ist, ist eine Funktion, und nur weil Es ist nicht gleich bedeutet nicht, dass es tatsächlich anders ist.

recompose.onlyUpdateForKeys stimme zu! Es gibt eine Kompromissalternative, um mit Inline -Funktionen umzugehen, die Methoden im Konstruktor und jede Erholung binden. Das ist das Feld der öffentlichen Klasse. Es handelt sich um eine Phase -2 -Funktion in Babel, sodass Ihr Setup es wahrscheinlich unterstützen wird. Zum Beispiel ist hier ein Zweig, der ihn verwendet, was nicht nur kürzer ist, sondern jetzt auch bedeutet, dass wir nicht alle nicht funktionsfähigen Requisiten manuell auflisten müssen. Diese Lösung muss Schließungen aufgeben. Trotzdem ist es immer noch gut, bei Bedarf

zu wissen und zu erkennen.

Weitere Informationen zu React finden Sie in unserem Kurs "React the ES6".

Dieser Artikel wurde von Jack Franklin von Experten überprüft. Vielen Dank an alle SitePoint -Peer -Rezensenten für die perfekte Erstellung von SitePoint!

häufig gestellte Fragen zur Optimierung der React -Leistung mit den Staatenlosenkomponenten

Was ist der Hauptunterschied zwischen einer staatlichen Komponente und einer zustandslosen Komponente in React?

Zustandskomponenten (auch als Klassenkomponenten bezeichnet) behalten den Speicher über die Änderungen des Komponentenzustands im Laufe der Zeit bei. Sie sind dafür verantwortlich, wie Komponenten sich verhalten und rendern. Andererseits haben Staatlose Komponenten (auch Funktionskomponenten genannt) keinen eigenen Zustand. Sie empfangen Daten von der übergeordneten Komponente in Form von Requisiten und rendern sie. Sie sind hauptsächlich für den UI -Teil der Komponente verantwortlich.

Wie optimieren Sie die Leistung meiner React -Anwendung mit staatenlosen Komponenten?

PureComponent Staatelose Komponenten können die Leistung von React -Anwendungen erheblich verbessern. Da sie ihre eigenen Zustands- oder Lebenszyklus -Methoden nicht verwalten, haben sie weniger Code, was sie erleichtert, um sie zu verstehen und zu testen. Sie können auch die von der Anwendung verbrauchte Speichermenge reduzieren. Um die Leistung zu optimieren, können Sie Statuskomponenten so weit wie möglich in zustandslose Komponenten konvertieren und die

von React verwenden, um unnötige Wiederholungen zu vermeiden.

Was ist PureComponent und wie hilft es, die React -Leistung zu optimieren?

PureComponent ist eine spezielle React -Komponente, mit der die Leistung Ihrer Anwendung optimiert wird. Es verwendet einen flachen Requisiten- und Zustandsvergleich, um die Methode shouldComponentUpdate Lebenszyklus zu implementieren. Dies bedeutet, dass es sich nur dann erneut verändert, wenn sich der Status oder die Requisiten ändern, was die unnötige Wiederholung erheblich verringern und die Leistung verbessern kann.

Wie konvertieren Sie eine Zustandskomponente bei einer reagierten Aufenthaltskomponente?

Umwandlung einer Statuskomponente in eine zustandslose Komponente umfasst das Entfernen eines Zustands oder der Lebenszyklusmethode aus der Komponente. Die Komponente sollte nur Daten über Requisiten empfangen und sie rendern. Hier ist ein Beispiel:

// Statuskomponente Class Welcome erweitert React.comPonent { render () { return

Hallo, {this.props.name}
; } }

// Staatelose Komponente Funktion Willkommen (Requisiten) { return

Hallo, {props.name}
; }

Was sind die Best Practices für die Verwendung staatenloser Komponenten in React?

Einige Best Practices für die Verwendung von ReaceT -Komponenten für Staaten: Verwenden Sie so viele von ihnen, um die Leistung und die Lesbarkeit zu verbessern und sich auf eine einzige Funktion zu konzentrieren. Es wird auch empfohlen, die Props -Dekonstruktion zum Schreiben von Cleaner -Code zu verwenden.

Können staatenlose Komponenten Lebenszyklusmethoden in React verwenden?

Nein, Staatelose Komponenten können keine Lebenszyklusmethoden in React verwenden. Lebenszyklusmethoden sind nur für Klassenkomponenten anwendbar. Mit der Einführung von Hooks in React 16.8 können Sie jedoch Funktionskomponenten zu Status- und Lebenszyklusfunktionen hinzufügen.

Was sind die Einschränkungen der staatenlosen Komponenten in React?

Während die Staatenlose Komponenten viele Vorteile haben, haben sie auch einige Einschränkungen. Sie können keine Lebenszyklusmethoden anwenden oder ihren eigenen Zustand verwalten. Diese Einschränkungen können jedoch durch Verwendung von React -Hooks überwunden werden.

Wie können staatenlose Komponenten die Lesbarkeit von Code verbessern?

Staatelose Komponenten verbessern die Code -Lesbarkeit durch Einfachheit und Klarheit. Sie verwalten ihren eigenen Zustand nicht oder verwenden keine Lebenszyklusmethoden, was sie einfacher und einfacher zu verstehen macht. Sie fördern auch die Verwendung kleiner, wiederverwendbarer Komponenten, mit denen der Code organisierter und leichter zu warten ist.

Können staatenlose Komponenten Ereignisse in React verarbeiten?

Ja, staatenlose Komponenten können Ereignisse in React verarbeiten. Ereignishandler können als Requisiten an staatenlose Komponenten übergeben werden. Hier ist ein Beispiel:

Funktion actionLink (Props) { Zurückkehren ( Klicken Sie auf mich ); }

Wie fördern staatenlose Komponenten die Modularisierung von Code?

Staatelose Komponenten fördern die Modularisierung des Codes durch Förderung der Verwendung kleiner, wiederverwendbarer Komponenten. Jede Komponente kann unabhängig voneinander entwickelt und getestet werden, wodurch der Code leichter zu warten und zu verstehen ist. Es fördert auch die Trennung von Bedenken, bei denen jede Komponente für eine einzelne Funktion verantwortlich ist.

Das obige ist der detaillierte Inhalt vonOptimierung der Reaktionsleistung mit staatenlosen Komponenten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage