2016-05-23 12 views
33

ecco la mia situazione:React.js, attendere che setState termini prima di attivare una funzione?

  • su this.handleFormSubmit() sto eseguendo this.setState()
  • all'interno this.handleFormSubmit(), sto chiamando this.findRoutes(); - che dipende dal completamento riuscito di this.setState()
  • this.setState(); non viene completato prima che this.findRoutes venga chiamato ...
  • Come attendere che questo.setState() all'interno di this.handleFormSubmit() termini prima di chiamare this.findRoutes()?

Una soluzione scadente:

  • mettendo this.findRoutes() in componentDidUpdate()
  • questo non è accettabile perché ci saranno più cambiamenti di stato correlato funzioni degli findRoutes(). Non voglio attivare la funzione findRoutes() quando lo stato non correlato viene aggiornato.

Sono nuovo per reagire ... quindi per favore nudi con me!

Vedere codice qui sotto frammento di seguito:

handleFormSubmit: function(input){ 
       // Form Input 
       this.setState({ 
        originId: input.originId, 
        destinationId: input.destinationId, 
        radius: input.radius, 
        search: input.search 
       }) 
       this.findRoutes(); 
      }, 
      handleMapRender: function(map){ 
       // Intialized Google Map 
       directionsDisplay = new google.maps.DirectionsRenderer(); 
       directionsService = new google.maps.DirectionsService(); 
       this.setState({map: map}); 
       placesService = new google.maps.places.PlacesService(map); 
       directionsDisplay.setMap(map); 
      }, 
      findRoutes: function(){ 
       var me = this; 
       if (!this.state.originId || !this.state.destinationId) { 
        alert("findRoutes!"); 
        return; 
       } 
       var p1 = new Promise(function(resolve, reject) { 
        directionsService.route({ 
         origin: {'placeId': me.state.originId}, 
         destination: {'placeId': me.state.destinationId}, 
         travelMode: me.state.travelMode 
        }, function(response, status){ 
         if (status === google.maps.DirectionsStatus.OK) { 
          // me.response = response; 
          directionsDisplay.setDirections(response); 
          resolve(response); 
         } else { 
          window.alert('Directions config failed due to ' + status); 
         } 
        }); 
       }); 
       return p1 
      }, 
      render: function() { 
       return (
        <div className="MapControl"> 
         <h1>Search</h1> 
         <MapForm 
          onFormSubmit={this.handleFormSubmit} 
          map={this.state.map}/> 
         <GMap 
          setMapState={this.handleMapRender} 
          originId= {this.state.originId} 
          destinationId= {this.state.destinationId} 
          radius= {this.state.radius} 
          search= {this.state.search}/> 
        </div> 
       ); 
      } 
     }); 

risposta

82

setState() ha un parametro di callback facoltativo che è possibile utilizzare per questo. Hai solo bisogno di modificare il codice un po ', a questo:

// Form Input 
this.setState(
    { 
    originId: input.originId, 
    destinationId: input.destinationId, 
    radius: input.radius, 
    search: input.search 
    }, 
    this.findRoutes   // here is where you put the callback 
); 

Avviso la chiamata alla findRoutes è ora all'interno del setState() chiamata, come secondo parametro.
senza () perché si passa la funzione.

+0

Incredibile! Grazie mille – matthewalexander

+1

Mi hai salvato, grazie –

+0

Questo funzionerà bene per reimpostare un Valore Animato dopo setState in ReactNative. – SacWebDeveloper

1

Secondo i documenti di setState(), il nuovo stato potrebbe non essere riflesso nella funzione di richiamata findRoutes(). Ecco l'estratto da React docs:

setState() non muta immediatamente questo.stato ma crea una transizione di stato in sospeso. L'accesso a this.state dopo aver chiamato questo metodo può potenzialmente restituire il valore esistente.

Non esiste alcuna garanzia di funzionamento sincrono delle chiamate su setState e le chiamate possono essere raggruppate per ottenere prestazioni migliori.

Quindi ecco quello che ti propongo di fare. È necessario passare i nuovi stati input nella funzione di richiamata findRoutes().

handleFormSubmit: function(input){ 
    // Form Input 
    this.setState({ 
     originId: input.originId, 
     destinationId: input.destinationId, 
     radius: input.radius, 
     search: input.search 
    }); 
    this.findRoutes(input); // Pass the input here 
} 

La funzione findRoutes() dovrebbero essere definite in questo modo:

findRoutes: function(me = this.state) { // This will accept the input if passed otherwise use this.state 
    if (!me.originId || !me.destinationId) { 
     alert("findRoutes!"); 
     return; 
    } 
    var p1 = new Promise(function(resolve, reject) { 
     directionsService.route({ 
      origin: {'placeId': me.originId}, 
      destination: {'placeId': me.destinationId}, 
      travelMode: me.travelMode 
     }, function(response, status){ 
      if (status === google.maps.DirectionsStatus.OK) { 
       // me.response = response; 
       directionsDisplay.setDirections(response); 
       resolve(response); 
      } else { 
       window.alert('Directions config failed due to ' + status); 
      } 
     }); 
    }); 
    return p1 
}