同时运行异步函数未更新状态变量

huangapple go评论66阅读模式
英文:

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 同时运行异步函数未更新状态变量

huangapple
  • 本文由 发表于 2023年6月22日 15:34:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定