beautiful-react-hooks
Version:
A collection of beautiful (and hopefully useful) React hooks to speed-up your components and hooks development
50 lines (49 loc) • 2.26 kB
JavaScript
import { useCallback, useEffect, useState } from 'react';
import createHandlerSetter from './factory/createHandlerSetter';
import useGeolocationEvents from './useGeolocationEvents';
import { geoStandardOptions, isSamePosition, makePositionObj } from './shared/geolocationUtils';
/**
* Returns a frozen object containing the `position` object, the `isSupported` boolean flag, reporting whether the
* geolocation API is supported or not and the `isRetrieving` boolean flag reporting whether the hook is fetching the
* current position.
* The position is retrieved by using the
* [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API/Using_the_Geolocation_API),
* when supported.<br/><br />
* It possibly accepts an object of [geolocation options]
* (https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions) to be used as parameter when using the
* `Geolocation.getCurrentPosition()` method.
*/
const useGeolocationState = (options = geoStandardOptions) => {
const [isRetrieving, setRetrieving] = useState(false);
const [position, setPosition] = useState(null);
const { isSupported, onChange, onError: setOnGeolocationEventsErrorRef } = useGeolocationEvents(options);
const [onCurrentPositionErrorRef, setOnCurrentPositionErrorRef] = createHandlerSetter();
const savePosition = useCallback(() => {
if (position === null) {
setRetrieving(true);
navigator.geolocation.getCurrentPosition((nextPosition) => {
if (!isSamePosition(position, nextPosition)) {
setPosition(makePositionObj(nextPosition));
setRetrieving(false);
}
}, (err) => {
if (onCurrentPositionErrorRef.current) {
onCurrentPositionErrorRef.current(err);
}
});
}
}, [position]);
useEffect(savePosition, [position]);
onChange(savePosition);
const onError = (callback) => {
setOnCurrentPositionErrorRef(callback);
setOnGeolocationEventsErrorRef(callback);
};
return Object.freeze({
onError,
isSupported,
isRetrieving,
position,
});
};
export default useGeolocationState;