Skip to content

Instantly share code, notes, and snippets.

@shikanime
Last active January 26, 2022 01:17
Show Gist options
  • Save shikanime/999b80eae6becc9acda9870560c0f6da to your computer and use it in GitHub Desktop.
Save shikanime/999b80eae6becc9acda9870560c0f6da to your computer and use it in GitHub Desktop.
Example of synchronizing the state of the recoil with the browser's geolocation API
import { useEffect } from "react";
import {
atom,
useRecoilCallback,
useRecoilValue,
useResetRecoilState,
useSetRecoilState,
} from "recoil";
export const optionsState = atom<PositionOptions>({
key: "optionsState",
default: {
enableHighAccuracy: undefined,
maximumAge: undefined,
timeout: undefined,
},
});
export const watchIdState = atom<number | null>({
key: "watchIdState",
default: null,
});
export const positionState = atom<GeolocationPosition | null>({
key: "positionState",
default: null,
});
export const positionErrorState = atom<GeolocationPositionError | null>({
key: "positionErrorState",
default: null,
});
export const useUnwatchPosition = () => {
const resetWatcherIdState = useResetRecoilState(watchIdState);
return useRecoilCallback(
({ snapshot }) =>
async () => {
const watchId = await snapshot.getPromise(watchIdState);
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
resetWatcherIdState();
}
},
[resetWatcherIdState]
);
};
export const useWatchPosition = () => {
const setPositionState = useSetRecoilState(positionState);
const setWatchIdState = useSetRecoilState(watchIdState);
const setPositionErrorState = useSetRecoilState(positionErrorState);
const unwatchPosition = useUnwatchPosition();
return useRecoilCallback(
({ snapshot }) =>
async () => {
const locationOptions = await snapshot.getPromise(optionsState);
await unwatchPosition();
setWatchIdState(
navigator.geolocation.watchPosition(
setPositionState,
setPositionErrorState,
locationOptions
)
);
},
[setPositionState]
);
};
export const LocationPageOnLoad = () => {
const watchPosition = useWatchPosition();
const unwatchPosition = useUnwatchPosition();
const position = useRecoilValue(positionState);
useEffect(() => {
watchPosition();
return () => {
unwatchPosition();
};
}, [watchPosition, unwatchPosition]);
return (
<div>
<>Your current position is: {JSON.stringify(position)}</>
</div>
);
};
export const LocationPageOnClick = () => {
const watchPosition = useWatchPosition();
const unwatchPosition = useUnwatchPosition();
const position = useRecoilValue(positionState);
useEffect(() => {
return () => {
unwatchPosition();
};
}, [unwatchPosition]);
return (
<div>
<button onClick={watchPosition}>Watch Position</button>
<>Your current position is: {JSON.stringify(position)}</>
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment