Quando utilizzare il callback di React setState


191

Quando uno stato del componente di reazione cambia, viene chiamato il metodo di rendering. Quindi per qualsiasi cambiamento di stato, un'azione può essere eseguita nel corpo dei metodi di rendering. Esiste quindi un caso d'uso particolare per il callback setState?


4
Al momento non è chiaro quello che stai chiedendo. Puoi includere del codice?
Davin Tryon,

2
Il callback setState è per qualsiasi cosa tu voglia fare dopo che lo stato DEFINITELY è stato modificato. Poiché setState è asincrono, se si desidera chiamare un fx ed essere SICURI che il nuovo stato sia caricato, questo è lo scopo del callback
Jayce444

3
Il caso d'uso del callback setState è abbastanza chiaro. Lo si utilizza quando si desidera eseguire una funzione dopo l'aggiornamento di uno stato SPECIFICO. Se si inserisce questa funzione render(), verrà eseguita ogni volta che QUALSIASI stato viene aggiornato, che probabilmente non è quello che si desidera. Ciò renderà anche il tuo codice meno leggibile e logico.
M3RS

Risposte:


225

Sì, c'è, dal momento che setStatefunziona in un asynchronouscerto senso. Ciò significa che dopo aver chiamato setStatela this.statevariabile non viene immediatamente modificata. quindi se si desidera eseguire un'azione immediatamente dopo aver impostato lo stato su una variabile di stato e quindi restituire un risultato, sarà utile una richiamata

Considera l'esempio di seguito

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value });
  this.validateTitle();
},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

Il codice sopra riportato potrebbe non funzionare come previsto poiché la titlevariabile potrebbe non essere stata modificata prima che la convalida venga eseguita su di essa. Ora potresti chiederti che possiamo eseguire la convalida nella render()funzione stessa ma sarebbe meglio e in modo più pulito se potessimo gestirla nella funzione changeTitle stessa poiché ciò renderebbe il tuo codice più organizzato e comprensibile

In questo caso il callback è utile

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value }, function() {
    this.validateTitle();
  });

},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

Un altro esempio sarà quando vuoi dispatche azione quando lo stato è cambiato. vorrai farlo in un callback e non nel modo render()in cui verrà chiamato ogni volta che si verifica il reindirizzamento e quindi molti di questi scenari sono possibili dove è necessario il callback.

Un altro caso è a API Call

Un caso può sorgere quando è necessario effettuare una chiamata API in base a un particolare cambio di stato, se lo si fa nel metodo di rendering, verrà chiamato ad ogni onStatecambio di rendering o perché alcuni Prop sono passati alla Child Componentmodifica.

In questo caso, si desidera utilizzare a setState callbackper passare il valore di stato aggiornato alla chiamata API

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....

3
Capisco che è di natura asincrona. La mia domanda era: c'è qualcosa di specifico che solo il callback setState può essere usato per questo forse il corpo dei metodi di rendering potrebbe non supportare (Qualcosa a parte diciamo una migliore leggibilità del codice.)
Sahil Jain,

@SahilJain La convalida è l'esempio corretto, non si desidera gestirlo nella funzione render () perché quindi verrà chiamato ogni volta che si apportano modifiche a render () si vorrebbe chiamarlo solo quando cambia solo l'input e quindi nella funzione stessa
Shubham Khatri

React vieta di cambiare lo stato durante il rendering .. Quindi è giusto mettere la validazione nel callback.
webdeb,

if (this.title.length === 0) {dovrebbe essere this.state.title.lengthvero?
Dmitry Minkovsky,

4
Il caso del primo utilizzo non è probabilmente una buona idea. I callback di setState si attivano dopo il nuovo rendering, quindi stai causando un doppio rendering senza motivo. Questo è esattamente lo scopo dell'argomento della funzione (programma di aggiornamento). Puoi semplicemente eseguire setState(state => state.title.length ? { titleError: "Title can't be blank" } : null)e la modifica si accumulerà. Non sono necessari doppi rendering.
R Esmond,

47
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});

14
Grazie per questo frammento di codice, che potrebbe fornire un aiuto limitato e immediato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con altre domande simili. Si prega di modificare la risposta di aggiungere qualche spiegazione, tra le ipotesi che hai fatto.
Machavity,

1
Quando si desidera chiamare una funzione dopo che lo stato è cambiato, è possibile utilizzare il metodo
Araz Babayev,

cosa succede se si desidera impostare più porzioni di stato come nome, nome, ecc.?
Sumanth Varada,

44

Il 1. caso d'uso che mi viene in mente, è una apichiamata, che non dovrebbe andare nel rendering, perché verrà eseguito per il eachcambio di stato. E la chiamata API deve essere eseguita solo su un cambio di stato speciale e non su tutti i render.

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

Quindi per qualsiasi cambiamento di stato, un'azione può essere eseguita nel corpo dei metodi di rendering.

Pessima pratica , poiché il rendermetodo dovrebbe essere puro, significa che non devono essere eseguite azioni, cambiamenti di stato, chiamate API, basta comporre la vista e restituirla. Le azioni devono essere eseguite solo su alcuni eventi. Il rendering non è un evento, ma componentDidMountper esempio.


25

Prendi in considerazione la chiamata setState

this.setState({ counter: this.state.counter + 1 })

IDEA

setState può essere chiamato in funzione asincrona

Quindi non puoi fare affidamento this. Se la chiamata sopra è stata effettuata all'interno di una funzione asincrona thissi riferirà allo stato del componente in quel momento ma ci aspettavamo che ciò si riferisse alla proprietà all'interno dello stato al momento della chiamata setState o all'inizio dell'attività asincrona. E poiché l'attività era chiamata asincrona, la proprietà potrebbe essere cambiata nel tempo. Quindi non è affidabile usare la thisparola chiave per fare riferimento ad alcune proprietà dello stato, quindi usiamo la funzione di callback i cui argomenti sono previousState e props che significa che quando è stata eseguita l'attività asincrona ed era tempo di aggiornare lo stato usando setState call prevState farà riferimento allo stato ora quando setState non è ancora iniziato. Garantire l'affidabilità che nextState non sarebbe danneggiato.

Codice errato: porterebbe alla corruzione dei dati

this.setState(
   {counter:this.state.counter+1}
 );

Codice corretto con setState con funzione di richiamata:

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

Quindi ogni volta che abbiamo bisogno di aggiornare il nostro stato corrente al prossimo stato basato sul valore posseduto dalla proprietà proprio ora e tutto ciò sta accadendo in modo asincrono, è una buona idea usare setState come funzione di callback.

Ho provato a spiegarlo in codice qui CODICE PENNA

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.