Articles

Capire React ‘ setState ‘

I componenti React possono, e spesso lo fanno, avere uno stato. Lo stato può essere qualsiasi cosa, ma pensa a cose come se un utente abbia effettuato l’accesso o meno e visualizzi il nome utente corretto in base a quale account è attivo. O una serie di post sul blog. O se una modale è aperta o meno e quale scheda al suo interno è attiva.

React components with state render UI based on that state. Quando lo stato dei componenti cambia, anche l’interfaccia utente del componente.

Ciò rende importante capire quando e come modificare lo stato del componente. Alla fine di questo tutorial, dovresti sapere come funziona setState ed essere in grado di evitare le insidie comuni che molti di noi colpiscono quando imparano a reagire.

Il funzionamento di `setState ()`

setState() è l’unico modo legittimo per aggiornare lo stato dopo la configurazione iniziale dello stato. Supponiamo di avere un componente di ricerca e di voler visualizzare il termine di ricerca inviato da un utente.

Ecco la configurazione:

import React, { Component } from 'react'class Search extends Component { constructor(props) { super(props) state = { searchTerm: '' } }}

Stiamo passando una stringa vuota come valore e, per aggiornare lo stato disearchTerm, dobbiamo chiamaresetState().

setState({ searchTerm: event.target.value })

Qui, stiamo passando un oggetto asetState(). L’oggetto contiene la parte dello stato che vogliamo aggiornare che, in questo caso, è il valore di searchTerm. React prende questo valore e lo fonde nell’oggetto che ne ha bisogno. È un po ‘ come il componenteSearch chiede cosa dovrebbe usare per il valore disearchTerm esetState() risponde con una risposta.

Questo è fondamentalmente dando il via a un processo che React chiama riconciliazione. Il processo di riconciliazione è il modo in cui React aggiorna il DOM, apportando modifiche al componente in base alla modifica dello stato. Quando viene attivata la richiesta a setState(), React crea un nuovo albero contenente gli elementi reattivi nel componente (insieme allo stato aggiornato). Questo albero viene utilizzato per capire come l’interfaccia utente del componente Search dovrebbe cambiare in risposta al cambiamento di stato confrontandolo con gli elementi dell’albero precedente. React sa quali modifiche implementare e aggiornerà solo le parti del DOM dove necessario. Questo è il motivo per cui React è veloce.

Sembra molto, ma per riassumere il flusso:

  • Abbiamo una componente di ricerca che visualizza un termine di ricerca
  • termine di ricerca è attualmente vuota
  • L’utente invia un termine di ricerca
  • questo termine vengono acquisiti e memorizzati con setState come un valore
  • la Riconciliazione avviene e Reagire si accorge del cambiamento di valore
  • Reagire indica la componente di ricerca per aggiornare il valore e il termine di ricerca è unita in

Il processo di riconciliazione non necessariamente modificare l’intera struttura, tranne che in una situazione in cui la radice dell’albero è modificato come questo:

// old<div> <Search /></div>// new<span> <Search /></span>

Tutti i<div>tag diventano<span> tag e l’intero albero dei componenti verrà aggiornato di conseguenza.

La regola empirica è di non mutare mai direttamente lo stato. Utilizzare sempre setState() per cambiare stato. La modifica dello stato direttamente, come lo snippet sottostante, non causerà il ri-rendering del componente.

// do not do thisthis.state = { searchTerm: event.target.value}

Passando una funzione a `setState ()`

Per dimostrare ulteriormente questa idea, creiamo un semplice contatore che aumenta e diminuisce al clic.

Vedere la penna setState Pen di Kingsley Silas Chijioke (@kinsomicrote) su CodePen.

Registriamo il componente e definiamo il markup per l’interfaccia utente:

class App extends React.Component {state = { count: 0 }handleIncrement = () => { this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 })} render() { return ( <div> <div> {this.state.count} </div> <button onClick={this.handleIncrement}>Increment by 1</button> <button onClick={this.handleDecrement}>Decrement by 1</button> </div> ) }}

A questo punto, il contatore semplicemente incrementa o diminuisce il conteggio di 1 su ogni clic.

Ma cosa succede se volessimo aumentare o diminuire di 3? Potremmo provare a chiamaresetState() tre volte nel handleDecrement e handleIncrement funzioni come questa:

handleIncrement = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 })}

Se stai codificando a casa, potresti essere sorpreso di scoprire che non funziona.

Lo snippet di codice di cui sopra è equivalente a:

Object.assign( {}, { count: this.state.count + 1 }, { count: this.state.count + 1 }, { count: this.state.count + 1 },)

Object.assign() viene utilizzato per copiare i dati da un oggetto di origine a un oggetto di destinazione. Se i dati copiati dall’origine alla destinazione hanno tutti le stesse chiavi, come nel nostro esempio, l’ultimo oggetto vince. Ecco una versione più semplice di come funzionaObject.assign();

let count = 3const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3});console.log(object);// output: Object { count: 6 }

Quindi invece della chiamata che avviene tre volte, accade solo una volta. Questo può essere risolto passando una funzione a setState(). Proprio come passi gli oggetti a setState(), puoi anche passare le funzioni, e questa è la via d’uscita dalla situazione sopra.

Se modifichiamo la funzione handleIncrement per assomigliare a questa:

handleIncrement = () => { this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 }))}

can ora possiamo incrementare il conteggio tre volte con un clic.

In questo caso, invece di unire, React accoda le chiamate di funzione nell’ordine in cui vengono effettuate e aggiorna l’intero stato in cui è stato eseguito. Questo aggiorna lo stato di count a 3 invece di 1.

Accedi allo stato precedente utilizzando Updater

Quando si creano applicazioni React, ci sono momenti in cui si desidera calcolare lo stato in base allo stato precedente del componente. Non puoi sempre fidarti dithis.state per mantenere lo stato corretto immediatamente dopo aver chiamatosetState(), poiché è sempre uguale allo stato reso sullo schermo.

Torniamo al nostro esempio contatore per vedere come funziona. Diciamo che abbiamo una funzione che decrementa il nostro conteggio di 1. Questa funzione è simile a questa:

changeCount = () => { this.setState({ count: this.state.count - 1})}

Quello che vogliamo è la capacità di decrementare di 3. La funzionechangeCount() viene chiamata tre volte in una funzione che gestisce l’evento click, come questo.

handleDecrement = () => { this.changeCount() this.changeCount() this.changeCount()}

Ogni volta che si fa clic sul pulsante per decrementare, il conteggio diminuirà di 1 invece di 3. Questo perchéthis.state.count non viene aggiornato fino a quando il componente non è stato ri-renderizzato. La soluzione è usare un programma di aggiornamento. Un programma di aggiornamento consente di accedere allo stato corrente e metterlo da utilizzare immediatamente per aggiornare altri elementi. Quindi la funzionechangeCount() sarà simile a questa.

changeCount = () => { this.setState((prevState) => { return { count: prevState.count - 1} })}

Ora non dipendiamo dal risultato dithis.state. Gli stati di count sono costruiti l’uno sull’altro, quindi siamo in grado di accedere allo stato corretto che cambia ad ogni chiamata a changeCount().

setState()deve essere trattato in modo asincrono — in altre parole, non sempre aspettarsi che lo stato sia cambiato dopo aver chiamato setState().

conclusioni

Quando si lavora con setState(), queste sono le cose principali che dovete sapere:

  • Aggiornamento per lo stato di un componente deve essere fatto utilizzando setState()
  • È possibile passare un oggetto o una funzione setState()
  • il Passaggio di una funzione quando si può aggiornare stato più volte
  • non dipendono da questo.stato immediatamente dopo aver chiamato setState() e utilizzare invece la funzione updater.