All hooks / Page, device, and user
useGeolocation
The device's position, watched with navigator.geolocation.watchPosition and updated as it moves. Stops watching on unmount or when disabled.
Enabling it makes the browser ask the user for permission the first time, so pass enabled: false until the user asks for location (e.g. clicks "Use my location"). On the server and during hydration it returns the initial state: loading if enabled, with no position.
Import
import { useGeolocation } from '@vincent.ri/react-tils'
// or only this hook
import { useGeolocation } from '@vincent.ri/react-tils/useGeolocation'Usage
const [asked, setAsked] = useState(false)
const { loading, position, error } = useGeolocation({ enabled: asked })
if (!asked) return <button onClick={() => setAsked(true)}>Use my location</button>
if (loading) return <p>Locating…</p>
if (error) return <p>Could not get your location: {error.message}</p>
return <Map lat={position!.coords.latitude} lng={position!.coords.longitude} />Live demo
No prompt until you click.
When to use it
Showing the user on a map, sorting nearby results, or filling in a location after the user asks.
When not to
A rough region is enough; use IP-based location on the server, which needs no prompt. Don't enable it on page load: users deny unexpected prompts, and a denial is hard to undo. To check the permission without prompting, use usePermission('geolocation').
API
function useGeolocation(options?: GeolocationOptions): GeolocationState| Parameter | Description |
|---|---|
options | enabled, enableHighAccuracy, maximumAge, and timeout. All optional. |
Types
export type GeolocationOptions = {
/** Start watching. Default `true`. Pass `false` until the user asks, to avoid a prompt on page load. */
enabled?: boolean;
/** Ask for GPS-level accuracy. Slower and uses more battery. Default `false`. */
enableHighAccuracy?: boolean;
/** Accept a cached position up to this many milliseconds old. Default `0`. */
maximumAge?: number;
/** Give up after this many milliseconds per attempt. Default: no limit. */
timeout?: number;
};
export type GeolocationState = {
/** `true` while enabled and waiting for the first position or error. */
loading: boolean;
position: GeolocationPosition | null;
/** `GeolocationPositionError` (denied, unavailable, timeout), or an `Error` if the browser has no geolocation. */
error: GeolocationPositionError | Error | null;
};Browser support
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| GeolocationWidely available | 5+ | 12+ | 3.5+ | 5+ | 18+ | ≤3+ |
- Needs a secure page (HTTPS or localhost).
First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).