Skip to content

Instantly share code, notes, and snippets.

@KristofferEriksson
Created February 11, 2024 16:44
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save KristofferEriksson/ee5af0a52e1fea0acc028e9b10aa0969 to your computer and use it in GitHub Desktop.
Save KristofferEriksson/ee5af0a52e1fea0acc028e9b10aa0969 to your computer and use it in GitHub Desktop.
A React Typescript hook that provides real-time geolocation data, complete with heading and speed metrics
import { useEffect, useState } from "react";
interface LocationOptions {
enableHighAccuracy?: boolean;
timeout?: number;
maximumAge?: number;
}
interface LocationState {
coords: {
latitude: number | null;
longitude: number | null;
accuracy: number | null;
altitude: number | null;
altitudeAccuracy: number | null;
heading: number | null;
speed: number | null;
};
locatedAt: number | null;
error: string | null;
}
const useLocation = (options: LocationOptions = {}) => {
const [location, setLocation] = useState<LocationState>({
coords: {
latitude: null,
longitude: null,
accuracy: null,
altitude: null,
altitudeAccuracy: null,
heading: null,
speed: null,
},
locatedAt: null,
error: null,
});
useEffect(() => {
// Ensuring this runs only in a client-side environment
if (typeof window === "undefined" || !("geolocation" in navigator)) {
setLocation((prevState) => ({
...prevState,
error:
"Geolocation is not supported by your browser or not available in the current environment",
}));
return;
}
const handleSuccess = (position: GeolocationPosition) => {
setLocation({
coords: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy,
altitude: position.coords.altitude,
altitudeAccuracy: position.coords.altitudeAccuracy,
heading: position.coords.heading,
speed: position.coords.speed,
},
locatedAt: position.timestamp,
error: null,
});
};
const handleError = (error: GeolocationPositionError) => {
setLocation((prevState) => ({
...prevState,
error: error.message,
}));
};
const geoOptions = {
enableHighAccuracy: options.enableHighAccuracy || false,
timeout: options.timeout || Infinity,
maximumAge: options.maximumAge || 0,
};
const watcher = navigator.geolocation.watchPosition(
handleSuccess,
handleError,
geoOptions,
);
return () => navigator.geolocation.clearWatch(watcher);
}, [options.enableHighAccuracy, options.timeout, options.maximumAge]);
return location;
};
export default useLocation;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment