Last active
January 26, 2022 01:17
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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