Estoy escribiendo la siguiente función que debería obtener la ubicación actual del usuario y luego actualizar las propiedades de ubicación predefinidas:
export const getCurrentLocation = () => { const location = { userLat: '5', userLng: '' } navigator.geolocation.getCurrentPosition( (position) => { //getting the Longitude from the location json const currentLongitude = JSON.stringify(position.coords.longitude); //getting the Latitude from the location json const currentLatitude = JSON.stringify(position.coords.latitude); location.userLat = currentLatitude; console.log('lat: ', location.userLat); }, (error) => { console.warn(error); }, { enableHighAccuracy: false, timeout: 30000, maximumAge: 1000 }, ); return ( location ); } Comparé location.userLat con currentLatitude y esto se registra correctamente en la consola; sin embargo, cuando la función termina de ejecutarse, el userLat producido sigue siendo su valor inicial de 5 . Alternativamente, intenté usar ganchos useState para actualizar el valor, pero obtuve el error de invalid hook calls . Cualquier consejo o sugerencia sobre cómo hacer que refleje el valor actual de currentLatitude será apreciado.
Por lo que puedo decir, parece que getCurrentPosition es una función asíncrona. Tenga en cuenta que esto no significa que se declare async o que devuelva un objeto Promise que se puede await .
Puede convertir su función getCurrentLocation en una función async y envolver la llamada getCurrentPosition en una Promesa.
const getCurrentPosition = (options) => { return new Promise((resolve, reject) => { return navigator.geolocation.getCurrentPosition(resolve, reject, options)) }; }; export const getCurrentLocation = async (options) => { const location = { userLat: '5', userLng: '' }; try { const position = await getCurrentPosition(options); //getting the Longitude from the location json const currentLongitude = JSON.stringify(position.coords.longitude); //getting the Latitude from the location json const currentLatitude = JSON.stringify(position.coords.latitude); location.userLat = currentLatitude; location.userLng = currentLongitude; console.log('lat: ', location.userLat); } catch(error) { console.warn(error); } return location; }Código de consumo:
const options = { enableHighAccuracy: false, timeout: 30000, maximumAge: 1000, }; const { userLat, userLng } = await getCurrentLocation(options);Como dijo @Drew, obtener la ubicación está ocurriendo de forma asincrónica, por lo que el retun se está produciendo antes del console log . Otra forma de hablar de esto es transformar su función en un useState hook Al igual que:
import { useEffect, useState } from "react"; export const useGgetCurrentLocation = () => { const [location, setLocation] = useState({ userLat: "", userLng: "", }); const [fetchingLocation, setFetchingLocation] = useState(true); const [error, setError] = useState(""); useEffect(() => { navigator.geolocation.getCurrentPosition( (position) => { setLocation({ userLat: position.coords.latitude, userLng: position.coords.longitude }); setFetchingLocation(false); }, (error) => { console.warn(error); setError("Something went wrong!"); setFetchingLocation(false); }, { enableHighAccuracy: false, timeout: 30000, maximumAge: 1000, } ); }, []); return { location, fetchingLocation, error }; }; Y lo usarías como se muestra a continuación. Primero obtendría fetchingLocation que contiene true , luego se convierte en false , y ya sea que la ubicación sea exitosa o no, obtendría un error que contiene un mensaje o location que contiene la latitud y longitud reales.
const { location, fetchingLocation, error } = useGgetCurrentLocation();