2015-04-30 4 views
5

ho codifica miei ReactJS richieste AJAX come questo:emissione richiesta AJAX nel callback di setState()

this.setState({ 
    isLoading: true, 
    results: null 
}); 
$.get(ajaxUrl, function(results) { 
    this.setState({ 
     isLoading: false, 
     results: results 
    }); 
}.bind(this)); 

Questo è solo un esempio, manca la gestione degli errori, la limitazione, le richieste di cancellazione, ecc Ma l'essenza è lì. Fondamentalmente chiedo di impostare lo stato e quindi la richiesta di emissione.

Guardando qualche altro codice su GitHub, però, ho notato che alcune persone scrivono le loro chiamate AJAX nella richiamata setState:

this.setState({ 
    isLoading: true, 
    results: null 
}, function() { 
    $.get(ajaxUrl, function(results) { 
     this.setState({ 
      isLoading: false, 
      results: results 
     }); 
    }.bind(this)); 
}.bind(this)); 

C'è una ragione valida per farlo? The docs say:

Non vi è alcuna garanzia di funzionamento sincrono delle chiamate su setState e le chiamate possono essere raggruppate per guadagni di prestazioni.

Quindi non vi è alcuna garanzia che setState muti lo stato prima di tornare, ma non vedo alcuna menzione che diversi setState potrebbero eseguire fuori servizio. Quindi il peggio che potrebbe accadere è che lo stato di "caricamento" non viene mai reso. È questo che lo stile di quest'ultimo sta cercando di risolvere? C'è qualche altro rischio che non riesco a vedere?

risposta

3

ma vedo alcuna menzione che diversi dei setState possono eseguire fuori ordine

corretta vengono eseguiti in ordine, e dal punto di vista UX non si vuole mostrare un indicatore di caricamento per meno di mezzo secondo

Il caso per bisogno di questo più così:

this.setState({ 
    isLoading: true, 
    results: this.state.results || [] 
}, function() { 
    $.get(ajaxUrl, function(results) { 
     this.setState({ 
      isLoading: false, 
      // note! we're referring to state here 
      results: this.state.results.concat(results) 
     }); 
    }.bind(this)); 
}.bind(this)); 

Tuttavia, questo può anche essere risolto facendo passare un callback per setstate invece dell'oggetto. In questo modo, osserviamo lo stato dopo che si sono verificati gli aggiornamenti in coda precedenti.

È anche possibile passare una funzione con la funzione di firma (stato, oggetti di scena). Ciò può essere utile in alcuni casi quando si desidera che acceda un aggiornamento atomico che consulta il valore precedente di stato + oggetti di scena prima di impostare qualsiasi valore.
- Component Api Docs

this.setState({ 
    isLoading: true, 
    results: null 
}); 
$.get(ajaxUrl, function(results) { 
    this.setState(function(state){ 
     return { 
      isLoading: false, 
      results: state.results.concat(results) 
     }; 
    }); 
}.bind(this)); 

Per ottenere i migliori risultati, astratto tutto questo in un componente ad alto ordine o mixin. Non vuoi gestire questa logica in ogni componente che recupera i dati.