[korea-map-note] kakao location search api와 react-query 사용하기

쏘소·2022년 9월 28일
0

프로젝트

목록 보기
2/18

Promise화 하여 useQuery 사용

실제로 사용자가 지도에서 본인이 메모를 하고자 하는 위치를 정확히 마커로 클릭하기가 어렵다고 판단하였다. 그래서 searchBar 를 만들어서 키워드를 입력하면 장소 검색 결과들이 dropdown으로 보여지도록 하고 싶었다. 검색된 dropdown의 장소를 클릭하면 마커가 지도에 찍히면서 zoom-in 되도록 말이다.
react-kakao-map 공식문서에서 맵에서 search 기능을 이용하는 방법을 소개하고 있었다. 이를 따라서 코드를 작성하였다.

useSearchPlacesApi.ts

import { useEffect } from 'react'

const useSearchPlacesApi = (searchQuery: string, map: boolean) => {
  useEffect(() => {
    if (!map) return

    const searchPlaces = new kakao.maps.services.Places()
    searchPlaces.keywordSearch(searchQuery, (data, status) => {
      if (status === kakao.maps.services.Status.OK) {
        return data
      }
      if (status === kakao.maps.services.Status.ERROR) {
        new Error('에러 발생 했습니다.')
      }
      new Error('검색 결과가 없습니다.')
    })
  }, [map, searchQuery])
}

export default useSearchPlacesApi

DropDown.tsx

const DropDown = () => {
const searchPlacesResultData = useSearchPlacesApi(searchInput, map)
...
}

하지만 이렇게 하여 사용하려고 하니, search 후 사용하는 result data 가 서버에서 가져오는 데이터 이기도 하고(서버 데이터와 클라이언트 데이터 분리 원함), 로딩이나 fetching 과정을 따로 만들어주어야 하기도 하고, 또 캐싱 및 reFetching 시간 등을 세부적으로 다뤄주고 싶어 tanstack-query를 사용해주는 것이 좋겠다는 생각이 들었다.

Tanstack-Query 공식문서에 따르면,

To subscribe to a query in your components or custom hooks, call the useQuery hook with at least:

  • A unique key for the query
  • A function that returns a promise that:
  1. Resolves the data, or
  2. Throws an error

즉, 쿼리를 구독하려면(사용하려면) 유니크한 쿼리 키와 resolve 하는 데이터(결과 데이터)와 에러를 던지는 promise 함수와 함께 useQuery를 호출해야 한다는 것이다.
즉, 내가 위의 useSearchPlacesApi 훅을 promise 함수로 만들어야 useQuery를 정상적으로 사용해줄 수가 있다는 뜻이었다.

따라서 코드를 수정하여 다음과 같이 작성해주었다.

getSearchPlacesApi.ts

export const getSearchPlacesApi = (searchQuery: string, map: boolean) => {
  return new Promise((resolve, reject) => {
    if (!map) return
    const searchPlaces = new kakao.maps.services.Places()
    searchPlaces.keywordSearch(searchQuery, (data, status, _pagination) => {
      if (status === kakao.maps.services.Status.OK) {
        resolve(data)

      }
      if (status === kakao.maps.services.Status.ERROR) {
        reject(new Error('에러 발생 했습니다.'))
      }
      if (status === kakao.maps.services.Status.ZERO_RESULT) {
        reject(new Error('검색 결과가 없습니다.'))
      }
    })
  })
}

DropDown.tsx

const { isFetching, data } = useQuery(['getSearchPlaces', searchInput], () => getSearchPlacesApi(searchInput, map), {
    onSuccess: (res) => {
      console.log(res.data)
    },
    cacheTime: 1000 * 60 * 60,
    onError: (e) => console.log(e),
  })

  if (isFetching) {
    return <div>loading...</div>
  }

이렇게 해주니 정상적으로 kakao location search api를 useQuery와 함께 사용해줄 수 있었다.

profile
개발하면서 행복하기

0개의 댓글