Hooks
No hooks found in any category.
useGeolocation
sensorsInstallation
npx usehooks-cli@latest add use-geolocation
Description
A React hook for accessing the user's geolocation with support for both one-time position requests and continuous position watching, including comprehensive error handling and configuration options.
Parameters
Name | Type | Default | Description |
---|---|---|---|
options? | GeolocationOptions | { enableHighAccuracy: false, timeout: Infinity, maximumAge: 0 } | Geolocation API options for accuracy, timeout, and cache settings |
Return Type
GeolocationState & { getCurrentPosition: () => void, startWatching: () => void, stopWatching: () => void }
Property | Type | Description |
---|---|---|
loading | boolean | True when requesting location data |
latitude | number | null | Current latitude coordinate |
longitude | number | null | Current longitude coordinate |
accuracy | number | null | Accuracy of the position in meters |
altitude | number | null | Altitude above sea level in meters |
altitudeAccuracy | number | null | Accuracy of altitude measurement in meters |
heading | number | null | Direction of travel in degrees (0-360) |
speed | number | null | Current speed in meters per second |
timestamp | number | null | Timestamp when position was acquired |
error | GeolocationPositionError | null | Error object if geolocation failed |
getCurrentPosition | () => void | Get current position once |
startWatching | () => void | Start continuously watching position changes |
stopWatching | () => void | Stop watching position changes |
Examples
Current Location Display
Getting and displaying the user's current location
1const {
2 latitude,
3 longitude,
4 accuracy,
5 loading,
6 error,
7 getCurrentPosition
8} = useGeolocation({
9 enableHighAccuracy: true,
10 timeout: 10000
11});
12
13return (
14 <div>
15 <button onClick={getCurrentPosition} disabled={loading}>
16 {loading ? 'Getting Location...' : 'Get My Location'}
17 </button>
18
19 {error && (
20 <div className="error">
21 Error: {error.message}
22 </div>
23 )}
24
25 {latitude && longitude && (
26 <div className="location-info">
27 <p>Latitude: {latitude.toFixed(6)}</p>
28 <p>Longitude: {longitude.toFixed(6)}</p>
29 <p>Accuracy: ±{accuracy?.toFixed(0)}m</p>
30 </div>
31 )}
32 </div>
33);
Live Location Tracking
Continuously tracking user's position for navigation
1const {
2 latitude,
3 longitude,
4 speed,
5 heading,
6 loading,
7 error,
8 startWatching,
9 stopWatching
10} = useGeolocation({
11 enableHighAccuracy: true,
12 timeout: 5000,
13 maximumAge: 1000
14});
15
16const [isTracking, setIsTracking] = useState(false);
17
18const toggleTracking = () => {
19 if (isTracking) {
20 stopWatching();
21 setIsTracking(false);
22 } else {
23 startWatching();
24 setIsTracking(true);
25 }
26};
27
28return (
29 <div>
30 <button onClick={toggleTracking}>
31 {isTracking ? 'Stop Tracking' : 'Start Tracking'}
32 </button>
33
34 {loading && <div>📍 Getting location...</div>}
35
36 {latitude && longitude && (
37 <div className="tracking-info">
38 <h3>Current Position</h3>
39 <p>📍 {latitude.toFixed(6)}, {longitude.toFixed(6)}</p>
40 {speed && <p>🏃 Speed: {(speed * 3.6).toFixed(1)} km/h</p>}
41 {heading && <p>🧭 Heading: {heading.toFixed(0)}°</p>}
42 </div>
43 )}
44 </div>
45);
Distance Calculator
Calculating distance between user and a target location
1const { latitude, longitude, error, getCurrentPosition } = useGeolocation();
2const [targetLocation] = useState({ lat: 40.7128, lng: -74.0060 }); // NYC
3const [distance, setDistance] = useState(null);
4
5// Haversine formula for distance calculation
6const calculateDistance = (lat1, lon1, lat2, lon2) => {
7 const R = 6371; // Earth's radius in km
8 const dLat = (lat2 - lat1) * Math.PI / 180;
9 const dLon = (lon2 - lon1) * Math.PI / 180;
10 const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
11 Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
12 Math.sin(dLon/2) * Math.sin(dLon/2);
13 const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
14 return R * c;
15};
16
17useEffect(() => {
18 if (latitude && longitude) {
19 const dist = calculateDistance(
20 latitude, longitude,
21 targetLocation.lat, targetLocation.lng
22 );
23 setDistance(dist);
24 }
25}, [latitude, longitude, targetLocation]);
26
27return (
28 <div>
29 <button onClick={getCurrentPosition}>
30 Calculate Distance to NYC
31 </button>
32
33 {error && <div>Error: {error.message}</div>}
34
35 {distance && (
36 <div>
37 <p>Distance to New York City:</p>
38 <p><strong>{distance.toFixed(2)} km</strong></p>
39 </div>
40 )}
41 </div>
42);
Dependencies
react
Notes
- •Requires user permission to access location data
- •Works only in secure contexts (HTTPS) in most browsers
- •Automatically cleans up watch positions on component unmount
- •Provides comprehensive position data including altitude, speed, and heading
- •Supports both one-time position requests and continuous watching
- •Handles browser compatibility and provides meaningful error messages
Implementation
1'use client';
2
3import { useState, useEffect, useCallback, useRef } from "react";
4
5export interface GeolocationState {
6 loading: boolean;
7 accuracy: number | null;
8 altitude: number | null;
9 altitudeAccuracy: number | null;
10 heading: number | null;
11 latitude: number | null;
12 longitude: number | null;
13 speed: number | null;
14 timestamp: number | null;
15 error: GeolocationPositionError | null;
16}
17
18export interface GeolocationOptions {
19 enableHighAccuracy?: boolean;
20 timeout?: number;
21 maximumAge?: number;
22}
23
24const defaultOptions: GeolocationOptions = {
25 enableHighAccuracy: false,
26 timeout: Infinity,
27 maximumAge: 0,
28};
29
30export function useGeolocation(options: GeolocationOptions = defaultOptions) {
31 const [state, setState] = useState<GeolocationState>({
32 loading: true,
33 accuracy: null,
34 altitude: null,
35 altitudeAccuracy: null,
36 heading: null,
37 latitude: null,
38 longitude: null,
39 speed: null,
40 timestamp: null,
41 error: null,
42 });
43
44 const watchIdRef = useRef<number | null>(null);
45 const optionsRef = useRef(options);
46
47 // Update options ref when options change
48 useEffect(() => {
49 optionsRef.current = options;
50 }, [options]);
51
52 const onSuccess = useCallback((position: GeolocationPosition) => {
53 setState({
54 loading: false,
55 accuracy: position.coords.accuracy,
56 altitude: position.coords.altitude,
57 altitudeAccuracy: position.coords.altitudeAccuracy,
58 heading: position.coords.heading,
59 latitude: position.coords.latitude,
60 longitude: position.coords.longitude,
61 speed: position.coords.speed,
62 timestamp: position.timestamp,
63 error: null,
64 });
65 }, []);
66
67 const onError = useCallback((error: GeolocationPositionError) => {
68 setState((prev) => ({
69 ...prev,
70 loading: false,
71 error,
72 }));
73 }, []);
74
75 const getCurrentPosition = useCallback(() => {
76 if (!navigator.geolocation) {
77 onError({
78 code: 2,
79 message: "Geolocation is not supported by this browser.",
80 } as GeolocationPositionError);
81 return;
82 }
83
84 setState((prev) => ({ ...prev, loading: true, error: null }));
85 navigator.geolocation.getCurrentPosition(
86 onSuccess,
87 onError,
88 optionsRef.current
89 );
90 }, [onSuccess, onError]);
91
92 const startWatching = useCallback(() => {
93 if (!navigator.geolocation) {
94 onError({
95 code: 2,
96 message: "Geolocation is not supported by this browser.",
97 } as GeolocationPositionError);
98 return;
99 }
100
101 if (watchIdRef.current !== null) {
102 navigator.geolocation.clearWatch(watchIdRef.current);
103 }
104
105 setState((prev) => ({ ...prev, loading: true, error: null }));
106 watchIdRef.current = navigator.geolocation.watchPosition(
107 onSuccess,
108 onError,
109 optionsRef.current
110 );
111 }, [onSuccess, onError]);
112
113 const stopWatching = useCallback(() => {
114 if (watchIdRef.current !== null) {
115 navigator.geolocation.clearWatch(watchIdRef.current);
116 watchIdRef.current = null;
117 }
118 }, []);
119
120 // Cleanup on unmount
121 useEffect(() => {
122 return () => {
123 if (watchIdRef.current !== null) {
124 navigator.geolocation.clearWatch(watchIdRef.current);
125 }
126 };
127 }, []);
128
129 return {
130 ...state,
131 getCurrentPosition,
132 startWatching,
133 stopWatching,
134 };
135}
136