React Native GeoLocation.watchPosition() 在成功回调中使用状态的初始值

React Native GeoLocation.watchPosition() using Initial value of state in success callback

我正在制作一个“寻宝”小径应用程序。用户可以去一个位置,当他们到达那个位置时,一个动作就会发生。为了监控用户位置,我使用来自“react-native-geolocation-service”的 Gelocation.watchposition()。

兴趣点 (trailLocation) 是从我们的 API 中获取的,我用它设置了“trailLocation”状态,它正确更新并且一切看起来都不错。 (initialTrailLocation passed from previous screen)

    const [trailLocation, setTrailLocation] = useState(initialTrailLocation);

/**
     * Function to get the next trail location
     */
    let getNextLocation = async () => {
        setIsLoading(true);
        const credentials = await Keychain.getGenericPassword();
        await axios.get(BACKEND_URL + 'api/v1/trails/' + trail.id + '/user/' + credentials.username + '/next-location?include=trail_location_ar_object.ar_object.ar_object_resources', {
                headers: {
                    Authorization: 'Bearer ' + credentials.password,
                },
            },
        )
        .then(response => {
            setTrailLocation(response.data.data.trail_location);
            setIsLoading(false);
            setUserWithinRange(false);
        })
        .catch(error => {
            console.log(error);
        });
    };

    /**
     * Function called when the position changes
     */
    function newPositionHandler(data) {
        console.log("new position handler");
        let radius = 1000;
        let ky = 40000 / 360;
        console.log(trailLocation);
        let kx = Math.cos((Math.PI * trailLocation.lat) / 180.0) * ky;
        let dx = Math.abs(trailLocation.lon - data.coords.longitude) * kx;
        let dy = Math.abs(trailLocation.lat - data.coords.latitude) * ky;

        setDistance(Math.sqrt(dx * dx + dy * dy));
        console.log(Math.sqrt(dx * dx + dy * dy));
        console.log('-------------------');
        if(Math.sqrt(dx * dx + dy * dy) <= radius / 1000) {
            setUserWithinRange(true);
        } else {
            setUserWithinRange(false)
        }
    };

    /** Function called to initialise the watch position functionality */
    async function watchPosition() {
        console.log("watch position");
        Geolocation.watchPosition((data) => newPositionHandler(data), (error) => console.log(error),{
            enableHighAccuracy: false,
            timeout: 10000,
            maximumAge: 1000,
            distanceFilter: 5,
            },
        );
    };

但是,当 watchposition 的成功函数被触发时,它使用“trailLocation”状态的原始值,因此计算出用户位置和新的 trailLocation 点之间的距离是错误的。我不明白为什么这是因为所有其他函数都使用正确的状态值。我将这些值记录下来,我可以使用初始状态清楚地看到它,但是所有其他操作都使用当前状态并且新的 trailLocation 参数显示在屏幕上。

如有任何帮助,我们将不胜感激。我可以提供更多详细信息,这是我的第一个问题,所以请让我松懈 ;)

谢谢

  1. 删除等待
     axios.get(BACKEND_URL + 'api/v1/trails/' + trail.id + '/user/' + credentials.username + '/next-location?include=trail_location_ar_object.ar_object.ar_object_resources', {
                headers: {
                    Authorization: 'Bearer ' + credentials.password,
                },
            },
        )
        .then(response => {
            setTrailLocation(response.data.data.trail_location);
            setIsLoading(false);
            setUserWithinRange(false);
        })
        .catch(error => {
            console.log(error);
        });

或 2.

let getNextLocation = async () => {
        setIsLoading(true);
        const credentials = await Keychain.getGenericPassword();
        const response = await axios.get(BACKEND_URL + 'api/v1/trails/' + trail.id + '/user/' + credentials.username + '/next-location?include=trail_location_ar_object.ar_object.ar_object_resources', {
                headers: {
                    Authorization: 'Bearer ' + credentials.password,
                },
            },
        )
        if(response?.data?.data?.trail_location){
            setTrailLocation(response.data.data.trail_location);
       }
       setIsLoading(false);
       setUserWithinRange(false);
    };

您的函数中的数据已过时 - 通常称为“陈旧闭包”。当你写 Geolocation.watchPosition((data) => newPositionHandler(data), ... 时,函数是用当时存在的状态创建的。当函数运行时,此数据已过时。

您可以在这个相关问题中阅读有关此问题解决方案的更多信息: