React,setstate 不会在一个变量的 useEffect 函数内部激活,适用于另一个变量

React, setstate does not activate inside useEffect function for one variable, works for another

我正在尝试显示一张地图,其中包含用户当前位置以及一些其他几何图形。我可以访问这些数据并显示它们,但是当需要显示另一个页面时,我想取消订阅位置更新。为此,我需要一个 ID(根据 navigator.geolocation 的文档)。我试图将此 ID 存储在状态变量中,但由于某种原因我无法在我的 useEffect 函数中设置此 ID。

令人费解的是,我还将几何数据存储在一个状态变量中,我可以从 useEffect 循环内部设置它。我只是无法弄清楚 featureswatcherId 状态变量之间有什么区别。当我 运行 此代码时 waId 被设置,但观察者 ID 始终保持 -1,因此我无法使用它取消订阅位置更改事件。

import React, { useState, useEffect } from 'react';
import GeoJSON from 'ol/format/GeoJSON';
import Feature from 'ol/Feature';
import {Point} from 'ol/geom';
import {transform, fromLonLat} from 'ol/proj';
import MapWrapper from './Base_MapWrapper';

function Card_Map(props) {
    const [ features, setFeatures ] = useState([]);
    const [ watcherId, setWatcherId ] = useState(-1);

    useEffect( () => {
        const wktOptions = {
            dataProjection: 'EPSG:4326',
            featureProjection: 'EPSG:3857'
        }
        const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);

        let waId = -1;
        if (navigator.geolocation) {
            console.log('location available');
            waId = navigator.geolocation.watchPosition(function(position) {
                let coorArr = [position.coords.longitude, position.coords.latitude];
                let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
                let fPoint = new Feature({
                    geometry: new Point(newCoors)
                });
                let theFeatures = [fPoint, ...parsedFeatures];
                setFeatures(theFeatures);
            });
            console.log(waId);
            setWatcherId(waId);
        }
        else {
            setFeatures(parsedFeatures);
        }
        console.log(watcherId);

        //this is the destructor 
        return () => {
            if (watcherId != -1)
            {
                navigator.geolocation.clearWatch(watcherId);
            }
        }
    },[]);

    return (
        <div>
            <MapWrapper features={features} cssClass={props.cssClass} />
        </div>
    ) 
}

export default Card_Map

您的问题是您正在尝试使用 watcherId,它会在调用 setWatcherId.

之前保留值的引用

我很确定你有一条警告说你应该使用 watcherId 作为依赖项,但这会触发另一个 re-render 和一个新的集合等等。

你在这里实际上不需要状态,你可以只使用 waId 所以你应该得到以下结果:

function Card_Map(props) {
    const [ features, setFeatures ] = useState([]);

    useEffect( () => {
        const wktOptions = {
            dataProjection: 'EPSG:4326',
            featureProjection: 'EPSG:3857'
        }
        const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);

        let waId = -1;
        if (navigator.geolocation) {
            console.log('location available');
            waId = navigator.geolocation.watchPosition(function(position) {
                let coorArr = [position.coords.longitude, position.coords.latitude];
                let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
                let fPoint = new Feature({
                    geometry: new Point(newCoors)
                });
                let theFeatures = [fPoint, ...parsedFeatures];
                setFeatures(theFeatures);
            });
        }
        else {
            setFeatures(parsedFeatures);
        }

        //this is the destructor 
        return () => {
            if (waId != -1)
            {
                navigator.geolocation.clearWatch(waId);
            }
        }
    },[]);

    return (
        <div>
            <MapWrapper features={features} cssClass={props.cssClass} />
        </div>
    ) 
}

如果你确实需要在另一个地方使用id,保持状态,但仍然在清理函数中使用waId