React State Von Grund auf

Avatar of Kingsley Silas
Kingsley Silas am

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

Wenn Sie beginnen, React zu lernen, werden Sie mit dem Verständnis konfrontiert, was State ist. State ist in React von enormer Bedeutung und vielleicht ein Hauptgrund, warum Sie sich überhaupt mit React beschäftigt haben. Lassen Sie uns versuchen zu verstehen, was State ist und wie es funktioniert.

Was ist State?

State ist in React ein **einfaches JavaScript-Objekt**, mit dem Sie die Daten einer Komponente verfolgen können. Der State einer Komponente kann sich ändern. Eine Änderung des States einer Komponente hängt von der Funktionalität der Anwendung ab. Änderungen können auf Benutzerreaktionen, neue Nachrichten vom Server, Netzwerkanfragen oder beliebige andere Dinge zurückzuführen sein.

Der Komponentenzustand (Component state) wird als privat für die Komponente erwartet und von derselben Komponente gesteuert. Um Änderungen am State einer Komponente vorzunehmen, müssen Sie diese innerhalb der Komponente vornehmen – die Initialisierung und Aktualisierung des Komponentenzustands.

Klassenkomponenten

State ist nur für Komponenten verfügbar, die als **Klassenkomponenten** bezeichnet werden. Der Hauptgrund, warum Sie Klassenkomponenten gegenüber ihren Gegenstücken, den Funktionskomponenten, verwenden möchten, ist, dass Klassenkomponenten einen State haben können. Sehen wir uns den Unterschied an. Funktionskomponenten sind JavaScript-Funktionen, so wie diese

const App = (props) => {
  return (
    <div>
      { props }
    </div>
  )
}

Wenn die Funktionalität, die Sie von Ihrer Komponente benötigen, so einfach ist wie die oben genannte, dann ist eine Funktionskomponente die perfekte Wahl. Eine Klassenkomponente wird deutlich komplexer aussehen als das.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = { username: 'johndoe' }
  }
  render() {
    const { username } = this.state
    return(
      <div>
        { username }
      </div>
    )
  }
}

Oben setze ich den State des Benutzernamens der Komponente auf einen String.

Der Konstruktor

Laut der offiziellen Dokumentation ist der Konstruktor der richtige Ort, um den State zu initialisieren. Die Initialisierung des States erfolgt durch Zuweisung von this.state zu einem Objekt, wie Sie oben sehen können. Denken Sie daran: **State ist ein einfaches JavaScript-Objekt**. Der anfängliche State der App-Komponente wurde auf ein State-Objekt gesetzt, das den Schlüssel `username` und seinen Wert `johndoe` mit `this.state = { username: 'johndoe' }` enthält.

Die Initialisierung eines Komponentenzustands kann so komplex werden, wie Sie hier sehen können

constructor(props) {
  super(props)
  this.state = { 
    currentTime: 0,
    status: false, 
    btnOne: false, 
    todoList: [],
    name: 'John Doe'
  }
}

Zugriff auf State

Ein initialisierter State kann in der `render()`-Methode abgerufen werden, wie ich es oben getan habe.

render() {
  const { username } = this.state
  return(
    <div>
      { username }
    </div>
  )
}

Eine Alternative zum obigen Snippet ist

render() {
  return(
    <div>
      { this.state.username }
    </div>
  )
}

Der Unterschied besteht darin, dass ich im ersten Beispiel den Benutzernamen aus dem State extrahiert habe, aber er kann auch als `const status = this.state.username` geschrieben werden. Dank ES6-Destrukturierung muss ich diesen Weg nicht gehen. Lassen Sie sich nicht verwirren, wenn Sie so etwas sehen. Es ist wichtig zu wissen, dass ich den State dabei nicht neu zuweise. Die ursprüngliche Einrichtung des States erfolgte im Konstruktor und sollte nicht erneut vorgenommen werden – aktualisieren Sie niemals Ihren Komponentenzustand direkt.

Ein State kann mit `this.state.property-name` abgerufen werden. Vergessen Sie nicht, dass Sie neben dem Punkt, an dem Sie Ihren State initialisiert haben, `this.state` das nächste Mal verwenden, wenn Sie auf den State zugreifen möchten.

State aktualisieren

Der einzig zulässige Weg, den State einer Komponente zu aktualisieren, ist die Verwendung von `setState()`. Sehen wir uns an, wie das praktisch funktioniert.

Zuerst erstelle ich die Methode, die aufgerufen wird, um den Benutzernamen der Komponente zu aktualisieren. Diese Methode sollte ein Argument erhalten und es wird erwartet, dass sie dieses Argument verwendet, um den State zu aktualisieren.

handleInputChange(username) {
  this.setState({username})
}

Sie sehen hier wieder, dass ich ein Objekt an `setState()` übergebe. Sobald dies geschehen ist, muss ich diese Funktion an den Event-Handler übergeben, der aufgerufen wird, wenn sich der Wert eines Eingabefeldes ändert. Der Event-Handler gibt den Kontext des ausgelösten Ereignisses an, wodurch es möglich wird, den in das Eingabefeld eingegebenen Wert mit `event.target.value` zu ermitteln. Dies ist das Argument, das an die `handleInputChange()`-Methode übergeben wird. Die Render-Methode sollte also wie folgt aussehen.

render() {
  const { username } = this.state
  return (
    <div>
      <div>
        <input 
          type="text"
          value={this.state.username}
          onChange={event => this.handleInputChange(event.target.value)}
        />
      </div>
      <p>Your username is, {username}</p>
    </div>
  )
}

Jedes Mal, wenn `setState()` aufgerufen wird, wird eine Anfrage an React gesendet, um das DOM mit dem neu aktualisierten State zu aktualisieren. Wenn Sie diese Denkweise haben, verstehen Sie, dass die State-Aktualisierung verzögert sein kann.

Ihre Komponente sollte wie folgt aussehen;

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = { username: 'johndoe' }
  }
  handleInputChange(username) {
    this.setState({username})
  }
  render() {
    const { username } = this.state
    return (
      <div>
        <div>
          <input 
            type="text"
            value={this.state.username}
            onChange={event => this.handleInputChange(event.target.value)}
          />
        </div>
        <p>Your username is, {username}</p>
      </div>
    )
  }
}

State als Props weitergeben

Ein State kann als Props von einer Eltern- an eine Kindkomponente weitergegeben werden. Um dies in Aktion zu sehen, erstellen wir eine neue Komponente zur Erstellung einer To-Do-Liste. Diese Komponente enthält ein Eingabefeld zum Eingeben von täglichen Aufgaben, und die Aufgaben werden als Props an die Kindkomponente weitergegeben.

Versuchen Sie, die Elternkomponente selbst zu erstellen, indem Sie die bisher gelernten Lektionen anwenden.

Beginnen wir mit der Erstellung des anfänglichen Zustands der Komponente.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = { todoList: [] }
  }
  render() {
    return()
  }
}

Der State der Komponente hat `todoList` auf ein leeres Array gesetzt. In der `render()`-Methode möchte ich ein Formular zum Absenden von Aufgaben zurückgeben.

render() {
  const { todoList } = this.state
  return (
    <div>
      <h2>Enter your to-do</h2>
      <form onSubmit={this.handleSubmit}>
        <label>Todo Item</label>
        <input
          type="text"
          name="todoitem"
        />
        <button type="submit">Submit</button>
      </form>
    </div >
  )
}

Jedes Mal, wenn ein neuer Eintrag eingegeben und der Submit-Button geklickt wird, wird die Methode `handleSubmit` aufgerufen. Diese Methode wird verwendet, um den State der Komponente zu aktualisieren. Ich möchte ihn mit `concat` aktualisieren, um den neuen Wert zum `todoList`-Array hinzuzufügen. Dies setzt den Wert für `todoList` innerhalb der `setState()`-Methode. Hier sehen Sie, wie das aussehen sollte

handleSubmit = (event) => {
  event.preventDefault()
  const value = (event.target.elements.todoitem.value)
  this.setState(({todoList}) => ({
    todoList: todoList.concat(value)
  }))
}

Der Ereigniskontext wird jedes Mal, wenn der Submit-Button geklickt wird, abgerufen. Wir verwenden `event.preventDefault()`, um die Standardaktion der Übermittlung zu stoppen, die die Seite neu laden würde. Der in das Eingabefeld eingegebene Wert wird einer Variable namens `value` zugewiesen, die dann als Argument übergeben wird, wenn `todoList.concat()` aufgerufen wird. React aktualisiert den State von `todoList`, indem es den neuen Wert zum anfänglichen leeren Array hinzufügt. Dieses neue Array wird zum aktuellen State von `todoList`. Wenn ein weiterer Eintrag hinzugefügt wird, wiederholt sich der Zyklus.

A chart illustrating the cycle explained above.

Das Ziel hier ist es, den einzelnen Eintrag als Props an eine Kindkomponente weiterzugeben. Für dieses Tutorial nennen wir sie `TodoItem`-Komponente. Fügen Sie den folgenden Codeausschnitt in die übergeordnete Div ein, die Sie in der `render()`-Methode haben.

<div>
  <h2>Your todo lists include:</h2>
  { todoList.map(i => <TodoItem item={i} /> )}
</div>

Sie verwenden `map`, um durch das `todoList`-Array zu iterieren, was bedeutet, dass der einzelne Eintrag dann als Props an die `TodoItem`-Komponente übergeben wird. Um dies zu nutzen, benötigen Sie eine `TodoItem`-Komponente, die Props empfängt und sie auf dem DOM rendert. Ich zeige Ihnen, wie das mit Funktions- und Klassenkomponenten funktioniert.

Geschrieben als Funktionskomponente

const TodoItem = (props) => {
  return (
    <div>
      {props.item}
    </div>
  )
}

Für die Klassenkomponente wäre es

class TodoItem extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    const {item} = this.props
    return (
      <div>
        {item}
      </div>
    )
  }
}

Wenn keine Notwendigkeit besteht, den State in dieser Komponente zu verwalten, ist es besser, eine Funktionskomponente zu verwenden.

Aufleveln

Sie werden beim Entwickeln von React-Anwendungen häufig mit State umgehen. Mit allen oben behandelten Bereichen sollten Sie das Vertrauen haben, sich mit dem fortgeschrittenen Teil des State-Managements in React zu beschäftigen. Um tiefer einzusteigen, empfehle ich die offizielle React-Dokumentation zu State and Lifecycle sowie den React Guide on Props vs State von Uber.