javascript - Ako môžem počkať, kým sa setState dokončí, pred spustením funkcie v React?
Tu je moja situácia:
- na this.handleFormSubmit() vykonávam this.setState()
- vo vnútri this.handleFormSubmit() volám this.findRoutes(); - čo závisí od úspešného dokončenia this.setState()
- this.setState(); sa nedokončí pred tým, než sa zavolá this.findRoutes...
- Ako čakám, kým this.setState() vo vnútri this.handleFormSubmit() skončí, predtým než zavolám this.findRoutes()?
Podpriemerné riešenie:
- vloženie this.findRoutes() do componentDidUpdate()
- Toto nie je prijateľné, pretože dôjde k viacerým zmenám stavu, ktoré nesúvisia s funkciou findRoutes(). Nechcem spúšťať funkciu findRoutes(), keď sa aktualizuje nesúvisiaci stav.
Prosím, pozrite si nasledujúci kódový útržok:
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>
);
}
});
Odpoveď č. 1
Metóda setState() má voliteľný parameter callback, ktorý môžete na toto použiť. Stačí, ak trochu zmeníte svoj kód na toto:
// 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
);
Všimnite si, že volanie findRoutes je teraz vnorené do volania setState() ako druhý parameter.
Bez (), pretože odovzdávate funkciu.
Odpoveď č. 2
Ak tu niekto pristál a má rovnakú situáciu pri používaní hookov, rovnaké správanie je možné dosiahnuť prostredníctvom nasledujúceho postupu
const [data, setData] = useState(false);
useEffect(() => {
doSomething(); // This will be executed when the state changes
}, [data]);
setData(true);
Tu sa useEffect spustí po akejkoľvek zmene v dátach a môžeme vykonať akúkoľvek závislú úlohu.
Odpoveď č. 3
this.setState({
originId: input.originId,
destinationId: input.destinationId,
radius: input.radius,
search: input.search
},
function() {
console.log("setState completed", this.state)
}
)
Odpoveď č. 4
setState prijíma nový stav a voliteľnú spätnú volaciu funkciu, ktorá sa volá po aktualizácii stavu.
this.setState(
{newState: 'whatever'},
() => {/*do something after the state has been updated*/}
)
Odpoveď č. 5
Podľa dokumentácie setState() sa nový stav nemusí prejaviť v spätnom volaní funkcie findRoutes(). Tu je úryvok z dokumentácie React:
setState() nezmení okamžite this.state, ale vytvorí čakajúci prechod stavu. Prístup k this.state po zavolaní tejto metódy môže potenciálne vrátiť existujúcu hodnotu.
Neexistuje žiadna záruka synchronného spustenia volaní setState a volania môžu byť kvôli zvýšeniu výkonu zoskupované.
Takže tu je to, čo navrhujem, aby ste urobili. Mali by ste odovzdať nové stavy input do spätného volania 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
}
Funkcia findRoutes() by mala byť definovaná takto:
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
}
