‘TMDB’에서 Search-Movies API
를 활용하여 영화를 검색하는 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에서 해당 영화의 데이터를 불러올 수 있도록 합니다.
const { data: searchMovie } = useQuery({
queryKey: ['search', searchKeyword],
queryFn: fetchSearch,
});
queryKey: ['search', searchKeyword]
queryKey
: 특정 커리를 식별하는데 사용되는 고유 키 (쿼리의 캐싱, 무효화 및 재요청을 관리하는데 중요한 역할)
- 배열 형태일 경우, 첫 번째 요소는 쿼리의 이름(문자열)이고 나머지 요소들은 쿼리의 매개변수로 사용됨
queryFn: fetchSearch
→ fetchSearch
함수 실행⇒ 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);