I'm writing a function that should get the user's current location and then update the predefined location properties.
The function:
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, thanks in advance
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 {useState} from "react";
export const useGgetCurrentLocation = () => {
const [location, setLocation] = useState({
userLat: "",
userLng: "",
});
const [fetchingLocation, setFetchingLocation] = useState(true);
const [error, setError] = useState("");
navigator.geolocation.getCurrentPosition(
(position) => {
setLocation({ userLat: position.coords.latitude, userLng: position.coords.longitude });
setFetchingLocation(false);
},
(error) => {
console.warn(error);
setError("Something went wrong!");
},
{
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()