긴 말 필요없이 코드부터 보자.
import { useCallback, useEffect, useState } from 'react'
interface UseCoordsState {
lat?: number
lon?: number
}
/**
* 위도 경도를 mount시 받아올 지 boolean 값으로 전달해주세요
* @param getCoordsOnMount
*/
const useGetCoords = (getCoordsOnMount = false) => {
const [enabled, setEnabled] = useState(getCoordsOnMount)
const [isLoading, setIsLoading] = useState(false)
const [coords, setCoords] = useState<UseCoordsState>({})
const successCallback = ({ coords: { latitude, longitude } }: GeolocationPosition) => {
setCoords({ lat: latitude, lon: longitude })
setTimeout(() => {
setIsLoading(false)
setEnabled(false)
}, 500)
}
const errorCallback = (error: unknown) => {
console.log(error)
}
const refetch = useCallback(() => {
if (enabled) {
return
}
setEnabled(true)
}, [enabled])
useEffect(() => {
if (!enabled) {
return
}
const watchId = navigator.geolocation.watchPosition(successCallback, errorCallback)
setIsLoading(true)
// Clean up the watchPosition method when the component unmounts
return () => navigator.geolocation.clearWatch(watchId)
}, [enabled])
return { refetch, coords, enabled, isLoading }
}
export default useGetCoords
이제 원하는 곳에서
원하는 바대로 사용하자.
지도 페이지 같은 경우는 getCoordsOnMount를 맘편하게 true로 주면 되겠다.
혹은 페이지 내 특정 버튼 클릭 시 유저의 위경도를 가져오겠다면 인자를 넘기지 않거나 false로 주면 되지 않을까 ?
또한 isLoading을 사용하여 위경도를 가져오는 동안 로딩 스피너를 보여줘도 된다.
const { coords, isLoading: getCoordsLoading, refetch: getCoords } = useGetCoords()
const { data: nearRegions } = useRegionQuery(coords, { enabled: !isEmpty(coords) })
const handleGetCoordsButtonClick = useCallback(
(value: string) => () => {
inputRef.current?.blur()
setRegion(value)
onDialogOpen()
},
[onDialogOpen]
)
const handleDialogAction = useCallback(() => {
pushRegionHistory(region)
onDialogClose()
}, [handlePushRegionHistoryList, onDialogClose, regionClickValue])
<Button onClick={() => delayedGetCoordsCall()}>
<RegionFocusIcon />
<span>내 위치로 찾기</span>
</Button>