Estoy tratando de mostrar un mapa con la ubicación actual de los usuarios combinada con alguna geometría adicional. Puedo acceder a estos datos y mostrarlos, pero cuando llega el momento de mostrar otra página, quiero darme de baja de las actualizaciones de ubicación. Para hacer esto necesito una identificación (según la documentación de navigator.geolocation ). Estoy tratando de almacenar esta identificación en una variable de estado, pero por alguna razón no puedo configurar esta identificación dentro de mi función useEffect .
Lo desconcertante es que también almaceno los datos de geometría en una variable de estado, y puedo configurarlo perfectamente desde dentro del bucle useEffect . Simplemente no puedo entender cuál es la diferencia entre las features y las variables de estado de watcherId . Cuando ejecuto este código, se establece waId , pero la identificación del observador siempre permanece -1 y, por lo tanto, no puedo usarla para cancelar la suscripción del evento de cambio de ubicación.
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_MapSu problema es el hecho de que está tratando de usar watcherId , que mantendrá una referencia del valor antes de llamar a setWatcherId .
Estoy bastante seguro de que tiene una advertencia que dice que debe usar watcherId como una dependencia, pero esto activará otra nueva representación y un nuevo conjunto, y así sucesivamente.
En realidad, no necesita un estado aquí, solo puede usar waId , por lo que debería terminar con lo siguiente:
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> ) } Si necesita la id en otro lugar, mantenga el estado, pero aún use waId en la función de limpieza.