"Find stores near me," a live-tracking map, a weather widget that defaults to your city — all need the device's location, which the browser exposes through the Geolocation API. It's permission-gated and asynchronous: the user might grant or deny it, a fix takes time, and watchPosition streams updates as they move. useGeolocation wraps that into a clean { loading, error, latitude, longitude, … } state.
Implement useGeolocation(options). Start in a loading state, subscribe with watchPosition, store each fix (coords + timestamp), capture errors (including "permission denied" and "unsupported"), and clear the watch on unmount.
function useGeolocation(options) {
// returns { loading, error, latitude, longitude, accuracy, timestamp }
}
const { loading, error, latitude, longitude } = useGeolocation();
if (loading) return <Spinner />;
if (error) return <p>{error.message}</p>;
return <Map lat={latitude} lng={longitude} />;
// Higher accuracy (uses GPS on mobile), with a timeout.
const pos = useGeolocation({ enableHighAccuracy: true, timeout: 5000 });
navigator.geolocation.watchPosition(onSuccess, onError, options) streams updates and returns a watch id; clearWatch(id) stops it.loading until the first fix or error; success fills coords and clears error; error sets error and stops loading.navigator.geolocation is undefined in insecure contexts / SSR; surface that as an error rather than crashing.clearWatch on unmount, and ignore any late callback that fires after the component is gone.