I'm writing the below function that should get the user's current location and then update the predefined location properties:
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
);
}
I equated location.userLat
to currentLatitude
and this logs correctly on the console, however when the function is done running, the produced userLat
is still its initial value of 5
. I alternatively tried using useState
hooks to update the value but got the error of invalid hook calls
. Any tips or suggestions on how to make it reflect the currentLatitude
value will be appreciated.
CodePudding user response:
From what I can tell it seems that getCurrentPosition
is an asynchronous function. Note that this doesn't mean it's declared async
or that it returns a Promise object that can be await
-ed on.
You can convert your getCurrentLocation
function to an async
function and wrap the getCurrentPosition
call in a Promise.
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;
}
Consuming code:
const options = {
enableHighAccuracy: false,
timeout: 30000,
maximumAge: 1000,
};
const { userLat, userLng } = await getCurrentLocation(options);
CodePudding user response:
As @Drew stated getting the location is happening asynchronously, so that retun
is happening before the console log
. Another way of talking this is to transform your function to a hook
, so you will be able to use useState
. Like so:
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 };
};
And you would use it as below. First you would get fetchingLocation
containing true
, then it becomes false
, and whether the location is successful or not, you would get error
containing a message or location
containing the actual latitude and longitude.
const { location, fetchingLocation, error } = useGgetCurrentLocation();