[TanStack Query] 검색 기능 구현

zzincode·2025년 2월 10일
0

ReviewZIP

목록 보기
3/7
post-thumbnail

검색 기능 구현

‘TMDB’에서 Search-Movies API를 활용하여 영화를 검색하는 api를 구하려고 합니다.

Search - Movies API 불러오기

Search-Movies API 의 query params를 살펴보면 query 가 필수 요소로 들어가야한다고 나와있습니다.

저는 영화이름을 검색하여 결과값을 내는 기능을 구현하고자 했기에 query를 영화 타이틀로 구현할 것입니다.

const BASE_PATH = 'https://api.themoviedb.org/3';

const fetchFromApi = async endpoint => {
  const response = await fetch(`${BASE_PATH}${endpoint}`, {
    headers: {
      Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`,
    },
  });
  return response.json();
};

export const fetchSearch = async ({ queryKey }) => {
  const [, searchKeyword] = queryKey;
  if (!searchKeyword) return [];
  return fetchFromApi(`/search/movie?query=${searchKeyword}&language=ko-KR}`);
};
  • queryKey 에서 검색어를 추출 const [, searchKeyword] = queryKey;

    배열 비구조화 할당
    : 배열에서 특정 값을 추출 - 배열의 요소를 변수에 쉽게 할당 가능

    • 가독성을 높이고 필요한 값만 쉽게 추출할 수 있음
      ⭐️ const [, searchKeyword] = queryKey;
      배열의 첫번째 요소를 무시하고 두번째 요소를 변수에 할당하겠다는 의미 ⇒ queryKey 배열의 첫번째 요소는 사용하지 않겠다
      searchKeyword는 사용자가 입력한 키워드의 상태변화값을 가지는 것이고 ‘search’는 무시되는 것이다.

  • 검색어가 없으면 빈배열 반환

⇒ 검색어를 추출하여 query에 검색어가 위치하여 Search API에서 해당 영화의 데이터를 불러올 수 있도록 합니다.

useQuery를 활용하여 서버로부터 데이터 불러오기

 const { data: searchMovie } = useQuery({
    queryKey: ['search', searchKeyword], 
    queryFn: fetchSearch,
  });
  • queryKey: ['search', searchKeyword]

    queryKey

    : 특정 커리를 식별하는데 사용되는 고유 키 (쿼리의 캐싱, 무효화 및 재요청을 관리하는데 중요한 역할)

    • 배열 형태일 경우, 첫 번째 요소는 쿼리의 이름(문자열)이고 나머지 요소들은 쿼리의 매개변수로 사용됨
  • queryFn: fetchSearchfetchSearch 함수 실행

searchKeyword가 바뀔 때마다 새로운 queryKey가 만들어지므로 검색어가 바뀔 때마다 API를 다시 호출합니다.

데이터 필터링 함수 + 검색 시 적용

export const filterMovies = (data, keyword) => {
  return data.filter(item =>
    item.title.toLowerCase().includes(keyword.toLowerCase()),
  );
};

  const handleSubmit = e => {
    e.preventDefault();
    if (searchKeyword.trim() === '') {
      handleReset();
      return;
    }
    setSearchKeyword(searchKeyword);
    const filteredList = filterMovies(searchMovie.results, searchKeyword);
    setSearchResult(filteredList);
    setSubmitted(true);
    handleAdd(searchKeyword);
  };

🚨 에러 발생

Uncaught TypeError: Cannot read properties of undefined (reading 'results')

⇒ 불러온 search 데이터가 아직 로드되지 않았을 떄 data가 undefined인 상황이라서 에러가 발생한 것

data?.results.filter(...)

?(옵셔널 체이닝)을 사용하여 undefined 방지하여 에러를 방지하도록 수정하였습니다.

export const filterMovies = (data, keyword) => {
  return data?.filter(item =>
    item.title.toLowerCase().includes(keyword.toLowerCase()),
  );
};
const filteredList = filterMovies(searchMovie?.results, searchKeyword);

0개의 댓글