Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

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

I am trying to display a map with the users current location combined with some additional geometry. I can access these data and display them, but when it is time to show another page I want to unsubscribe from the location updates. To do this I need an id (according to the documentation of the navigator.geolocation). I am trying to store this id in a state variable, but for some reason I cannot set this id inside my useEffect function.

The puzzling thing is that I also store the geometry data in a state variable, and I can set that just fine from inside the useEffect loop. I just cannot figure out what is the difference between the features and the watcherId state variables. When I run this code the waId gets set, but the watcher id always remains -1, and therefore I cannot use it to unsubscribe from the location changed event.

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
about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Your problem is the fact that you are trying to use watcherId which will keep a reference of the value before calling setWatcherId.

I'm pretty sure that you have a warning saying that you should use watcherId as a dependency, but this will trigger another re-render and a new set and so on.

You don't actually need a state here, you can just use waId so you should end up with the following:

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>
    ) 
}

If you do need the id in another place, keep the state, but still use waId in the cleanup function.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda