React.js, дождитесь завершения setState перед запуском функции?
вот моя ситуация:
- this.handleFormSubmit() Я выполняю this.setState()
- внутри this.handleFormSubmit(), я вызываю this.findRoutes(); - что зависит от успешного завершения this.setState()
- this.setState(); не завершается до этого .findRoutes вызывается...
- Как подождать this.setState() внутри this.handleFormSubmit() до завершения вызова this.findRoutes()?
Подпарарное решение:
- установка this.findRoutes() в componentDidUpdate()
- это неприемлемо, потому что будет больше изменений состояния, не связанных с функцией findRoutes(). Я не хочу запускать функцию findRoutes() при обновлении состояния, не связанного с ней.
Я новичок в реакции... так что, пожалуйста, со мной!
Ниже приведен фрагмент ниже:
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>
);
}
});
Ответы
Ответ 1
setState()
имеет необязательный параметр обратного вызова, который вы можете использовать для этого. Вам нужно лишь немного изменить свой код, чтобы:
// 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
);
Обратите внимание, что вызов findRoutes
теперь находится внутри вызова setState()
как второй параметр.
Без ()
, потому что вы передаете функцию.
Ответ 2
В соответствии с документами setState()
новое состояние может не отображаться в функции обратного вызова findRoutes()
. Вот выдержка из React docs:
setState() не сразу мутирует this.state, но создает ожидающий переход состояния. Доступ к this.state после вызова этого метода может потенциально вернуть существующее значение.
Нет гарантии синхронной работы вызовов setState, и вызовы могут быть собраны для повышения производительности.
Итак, вот что я предлагаю вам делать. Вы должны передать новые состояния input
в функцию обратного вызова 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
}
Функция findRoutes()
должна быть определена следующим образом:
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
}