React.js, чекайте завершення setState перед запуском функції?


107

Ось моя ситуація:

  • на цьому.handleFormSubmit () я виконую цей.setState ()
  • всередині цього.handleFormSubmit () я дзвоню це.findRoutes (); - від цього залежить успішне завершення цього.setState ()
  • this.setState (); не завершується до виклику цього.findRoutes ...
  • Як я зачекаю, коли завершиться this.setState () всередині цього.handleFormSubmit (), перш ніж викликати this.findRoutes ()?

Підрозділ:

  • поміщаючи this.findRoutes () у компонентDidUpdate ()
  • це не прийнятно, оскільки буде більше змін у стані, не пов’язаних із функцією 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>
                );
            }
        });

Відповіді:


247

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
Дивовижний! Велике спасибі
malexanders

Це буде добре працювати для скидання AnimatedValue після setState в ReactNative.
SacWebDeveloper


2
Родова версіяthis.setState({ name: "myname" }, function() { console.log("setState completed", this.state) })
Сасі Варунан

Не схоже, що ви можете передати більше, ніж один зворотний виклик setState. Чи є безладний спосіб прикування зворотних дзвінків? Скажімо, у мене є 3 методи, які потрібно запустити, і всі стану оновлення. Який найкращий спосіб впоратися з цим?
Шон

17
       this.setState(
        {
            originId: input.originId,
            destinationId: input.destinationId,
            radius: input.radius,
            search: input.search
        },
        function() { console.log("setState completed", this.state) }
       )

це може бути корисним


10

Згідно з документами setState()нового стану, можливо, не відображається функція зворотного виклику findRoutes(). Ось витяг із документів React :

setState () не одразу мутує цей.state, але створює перехід у стані очікування. Доступ до цього.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
}

у цього є серйозний недолік - передача буквального дозволу, setState()оскільки нова держава не є доброю, тому що це призводить до умов перегонів
тар

ось ще одна цитата з документів реагування (яка могла бути оновлена ​​після опублікування вашої відповіді): "... використовувати компонентDidUpdate або зворотний виклик setState (setState (оновлення, зворотний зв'язок))", будь-який з яких гарантовано запуститься після оновлення. застосовано ". Це говорить мені, що новий стан, безумовно, відображається на функції зворотного виклику.
Енді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.