英文:
Running async functions simultaneously not updating state variable
问题
我正在使用ReactJS,并尝试将Google Maps Directions API返回的折线存储在状态变量中,以便稍后有条件地渲染。这是存储第一和第二折线的状态变量:
const [routes, setRoutes] = useState({1: null, 2: null})
问题是,当我通过异步函数更新它们时,出于某种原因只有第二个字段会更新。
这是函数调用:
useEffect(() => {
drawTaxiRoute(0, data.taxis, data.origin, data.map, setRoutes, routes)
drawTaxiRoute(1, data.taxis, data.origin, data.map, setRoutes, routes)
}, [])
这是异步函数(我删除了async
关键字,但由于回调,它仍然异步运行):
function drawTaxiRoute(N = 0, taxis, destination, map, setRoutes, routes) {
...
directionsService.route(
{
origin: taxis[N].getPosition(),
destination: destination,
travelMode: google.maps.TravelMode.DRIVING,
},
function (result, status) {
if (status == 'OK') {
taxiRouteDisplay.setMap(map)
setRoutes({...routes, [N+1]: result})
console.log(result, N+1)
}
}
)
}
根据检查元素控制台,结果正确返回了折线,但routes
状态被错误地更新为一个为空的状态:
{1: null, 2: {...}}
我怀疑问题是routes
在第一次运行时没有及时更新,因为它是并行运行的,所以在第二个异步调用开始时仍然为null
并被覆盖。有人能提出一种填充routes
中的两个折线的方法吗?
谢谢!
英文:
I'm using ReactJS and trying to store the polyline returned by the Google Maps directions API in a state variable to be rendered conditionally later. This is the state variable that stores the first and second polylines:
const [routes, setRoutes] = useState({1: null, 2: null})
The problem is that when I update them through an asynchronous function, only the 2nd field updates for some reason
This is the function call
useEffect(() => {
drawTaxiRoute(0, data.taxis, data.origin, data.map, setRoutes, routes)
drawTaxiRoute(1, data.taxis, data.origin, data.map, setRoutes, routes)
}, [])
And this is the async function (I removed the async
keyword but it still behaves asynchronously due to the callback)
function drawTaxiRoute(N = 0, taxis, destination, map, setRoutes, routes) {
...
directionsService.route(
{
origin: taxis[N].getPosition(),
destination: destination,
travelMode: google.maps.TravelMode.DRIVING,
},
function (result, status) {
if (status == 'OK') {
taxiRouteDisplay.setMap(map)
setRoutes({...routes, [N+1]: result})
console.log(result, N+1)
}
}
)
}
According to the inspect element console, results is correctly returning the polyline, but the routes
state is being incorrectly updated such that one is null:
{1: null, 2: {...}}
I suspect the issue is that routes
is not updated in time for first time since it's running in parallel so it's still null
when the 2nd async invocation starts and gets overwritten. Can anyone suggest a way to populate both polylines in route
?
Thanks
答案1
得分: 1
最后一次调用会覆盖第一次调用,因为当调用setRoutes
时,routes
的值仍然是drawTaxiRoutes
参数传递的那个值。
如果你不知道,由useState
返回的setter方法可以接受两种类型的参数:变量的类型和返回新值的回调函数。
这个回调函数接受一个参数,即变量的当前值。
所以,你可以像这样做,而不是将routes
作为方法的参数传递:
setRoutes((oldValue) => ({...oldValue, [N+1]: result}))
这样,oldValue
的值将始终是最后更新的值。
希望这有所帮助
英文:
The last call will overwrite the first, because when setRoutes
is called, the value of routes
is still the one passed on the parameter of drawTaxiRoutes
If you don't know, the setter method returned by useState
can take two types of arguments: the type of the variable, and a callback returning the new value.
This callback takes one parameter, the current value of the variable.
So instead of passing routes
as a parameter of your method, you can do something like this :
setRoutes((oldValue) => ({...oldValue, [N+1]: result}))
That way, the value of oldValue
will always be the last updated value.
Hope it helps
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论