如何等待 setState 结束才触发 React 中的函数?

我的情况是这样的:

  • 在 this. handleFormSubmit ()上,我正在执行 this. setState ()
  • 在 this. handleFormSubmit ()中,我调用 this. findRoutes () ;-这取决于 this. setState ()的成功完成
  • SetState () ; 在 this 之前没有完成。
  • 在调用 this.findRoutes ()之前,如何等待 this.setState ()内部的 this.handleFormSubmit ()完成?

一个不合格的解决方案:

  • 将 this. findRoutes ()放到 Component entDidUpdate ()中
  • 这是不可接受的,因为将有更多与 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>
);
}
});
191398 次浏览

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()调用内部, 作为第二个参数。
没有使用 (),因为要传递函数。

根据 setState()的文档,新的状态可能不会反映在回调函数 findRoutes()中。以下是 反应文件的节选:

SetState ()不会立即变异 this.state,而是创建一个挂起的状态转换。在调用此方法后访问 this.state 可能会返回现有值。

不能保证调用 setState 的同步操作,为了提高性能,可能会对调用进行批处理。

所以我建议你这么做。您应该在回调函数 findRoutes()中传递新的状态 input

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
}
this.setState({
originId: input.originId,
destinationId: input.destinationId,
radius: input.radius,
search: input.search
},
function() {
console.log("setState completed", this.state)
}
)

为什么不多回答一个问题?当您调用 componentDidMount()(第一次执行 render())和/或 componentDidUpdate()(执行 render()之后的任何时间)时,setState()setState()触发的 render()都已完成执行。(链接是 ReactJS.org 的文档。)

例如 componentDidUpdate()

呼叫者,设置引用和设置状态..。

<Cmp ref={(inst) => {this.parent=inst}}>;
this.parent.setState({'data':'hello!'});

为人父母。

componentDidMount() {           // componentDidMount() gets called after first state set
console.log(this.state.data);   // output: "hello!"
}
componentDidUpdate() {          // componentDidUpdate() gets called after all other states set
console.log(this.state.data);   // output: "hello!"
}

例如 componentDidMount()

呼叫者,设置引用和设置状态..。

<Cmp ref={(inst) => {this.parent=inst}}>
this.parent.setState({'data':'hello!'});

为人父母。

render() {              // render() gets called anytime setState() is called
return (
<ChildComponent
state={this.state}
/>
);
}

在父级重新呈现子级之后,请参见 componentDidUpdate()中的状态。

componentDidMount() {           // componentDidMount() gets called anytime setState()/render() finish
console.log(this.props.state.data); // output: "hello!"
}

setState接受新的状态和可选的回调函数,该函数在状态更新后调用。

this.setState(
{newState: 'whatever'},
() => {/*do something after the state has been updated*/}
)

如果有人在这里着陆,并有相同的情况下使用钩子,同样的行为可以通过下面的过程实现

const [data, setData] = useState(false);


useEffect(() => {
doSomething(); // This is be executed when the state changes
}, [data]);


setData(true);

在这里,useEffect将在数据发生任何变化后运行,我们可以执行任何依赖任务。