I have got some very simple code:
const onSuccess = () => {
console.log('success');
}
const onError = () => {
console.log('error');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
My actual code contains a bit more logic. But for simplicity, I have posted only the required code.
success is printed to the console.So far so good...
success logged in the console.Now, if user blocks the geolocation and if he again allows the browser to use geolocation, at that time also, success should be logged. But on every refresh, it should not log success.
So, I believe, there should be some kind of eventlistener on allow button, but I don't see it mentioned anywhere.
I am not sure if I am going in the right direction, but...
On MDN docs here, I can see that there is something called PermissionStatus.onchange.
But it is experimental and not supported on Internet Explorer, Safari and Safari iOS.
If any one of you have used any alternatives, then I would love to check your ideas.
I am developing a weather application. The requirement is:
When user lands on the site, he should be asked for geolocation permission (if not already granted)
Once user grants permission, He should be taken to the page where he can see weather details of his city.
Current problem is that everytime, I refresh the page, it detects the location of the user and takes the user to his city details page. This is bad. This should only happen once, only when user grants access to geolocation.
I am getting some suggestions to store the user's permission status to local-storage.
But if I store the permission in local-storage then I have some problems.
Let me explain in detail by taking an example.
Part till when everything works fine:
When I get problems:
After waiting for sometime, I did not get any solutions other than using local-storage. So, I took a mixed approach. In my approach, I use navigator.permissions on whichever browser has implemented it and for other browsers, I use localstorage.
I am using react, so my solution includes react code, but still the idea can be used for pure javascript or for any javascript framework.
I have created a custom hook for that:
useGeoLocation.ts
import { useState, useEffect } from 'react';
interface Coordinates {
latitude: number;
longitude: number;
};
const useGeoLocation = (localStorageKey = 'is-location-granted') => {
const [shouldRequestLocation, setShouldRequestLocation] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<GeolocationPositionError>();
const [coords, setCoords] = useState<Coordinates>();
const onSuccess = (location: GeolocationPosition) => {
setLoading(false);
setCoords({
latitude: location.coords.latitude,
longitude: location.coords.longitude,
});
if (!('permissions' in navigator)) {
localStorage.setItem(localStorageKey, JSON.stringify(true));
}
}
const onError = (error: GeolocationPositionError) => {
setLoading(false);
setError(error);
}
useEffect(() => {
if ('permissions' in navigator) {
navigator.permissions.query({ name: 'geolocation' }).then((permissionStatus) => {
if (permissionStatus.state !== 'granted') {
setShouldRequestLocation(true);
}
});
} else {
const isLocationGranted = JSON.parse(localStorage.getItem(localStorageKey) || 'false');
if (!isLocationGranted) {
setShouldRequestLocation(true);
}
}
}, []);
useEffect(() => {
if(!('geolocation' in navigator)) {
const geoError = new GeolocationPositionError();
setError({
...geoError,
message: 'Geolocation not supported'
});
} else if (shouldRequestLocation) {
setLoading(true);
navigator.geolocation.getCurrentPosition(
onSuccess,
onError,
{ enableHighAccuracy: false, timeout: 10000, maximumAge: 18000000 },
);
}
}, [shouldRequestLocation]);
return { loading, error, coords };
};
export default useGeoLocation;
The code is preety straight forward, but if anyone finds any difficulties, please let me know and I will update my answer accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With