# useGeoLocation > Browser geolocation state. - Category: Data - Package: `hookli` (install with `npm i hookli`) - Docs: https://hookli.vercel.app/docs/use-geo-location ## Signature ```ts useGeoLocation(): { location: GeolocationPosition | null; error: GeolocationError | Error | null } ``` ## Returns - `location`: `GeolocationPosition | null` — hookli's trimmed position type — just coords.latitude and coords.longitude. Null until the first reading arrives. - `error`: `GeolocationError | Error | null` — Permission denials, unsupported browsers and failed lookups all land here — read .message for display. Requesting starts on mount, so mount the hook behind a user gesture. ## Types ### GeolocationPosition hookli's trimmed reading — only the coordinates, not the full browser GeolocationPosition. - `coords.latitude`: `number` — Latitude in decimal degrees. - `coords.longitude`: `number` — Longitude in decimal degrees. ### GeolocationError Shape of a permission or lookup failure. - `code`: `number` — Numeric error code mirrored from the browser's GeolocationPositionError. - `message`: `string` — Human-readable reason for the failure. ## Usage ```tsx import { useState } from "react"; import { useGeoLocation } from "hookli"; function Coordinates() { const { location, error } = useGeoLocation(); if (error) return

{error.message}

; if (!location) return

Locating…

; const { latitude, longitude } = location.coords; return

{latitude.toFixed(4)}, {longitude.toFixed(4)}

; } export function Demo() { const [asked, setAsked] = useState(false); // The hook may prompt for permission as soon as it mounts — // keep it unmounted until a user gesture. if (!asked) { return ; } return ; } ``` ## Source `src/hooks/useGeoLocation.hook.ts` ```ts import { useEffect, useState } from "react"; interface GeolocationError { code: number; message: string; } type GeolocationPosition = { coords: { latitude: number; longitude: number }; }; interface GeolocationState { location: GeolocationPosition | null; error: GeolocationError | Error | null; } export const useGeoLocation = (): GeolocationState => { const [location, setLocation] = useState(null); const [error, setError] = useState(null); useEffect(() => { const getLocation = async () => { try { const position = await getCurrentPosition(); setLocation({ coords: { latitude: position.coords.latitude, longitude: position.coords.longitude, }, }); } catch (err) { setError(err as Error); } }; if (navigator.geolocation) { navigator.permissions .query({ name: "geolocation" }) .then((result) => { if (result.state === "granted") { getLocation(); } else if (result.state === "prompt") { navigator.geolocation.getCurrentPosition( () => getLocation(), (err) => setError(err), ); } else { setError(new Error("Geolocation permission denied")); } }) .catch((err) => setError(err)); } else { setError(new Error("Geolocation is not supported by this browser.")); } }, []); return { location, error }; }; function getCurrentPosition(): Promise { return new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition(resolve, reject); }); } ```