TMDB의 영화 데이터를 받아와 검색기능을 구현합니다.
TMDB의 search API는 url에 query로 보낸 값과 일치하는 제목의 영화들을 가져옵니다.
const { default: axios } = require("axios");
const key = "KEY_VALUE";
const instance = axios.create({
baseURL: url,
params: {
api_key: key,
language: "ko-KR",
},
});
const category = {
search: "search/movie?query=",
};
export { instance, category };
1. App.js 에서 get으로 데이터를 받아오기위해서 useState에 입력받을 Query를 저장시킵니다.
const [searchList, setSearchList] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
2. get으로 url주소 + ?query=[searchQuery] 에서 데이터를 받아와 searchList 스테이트에 저장하도록 합니다.
const getTMDBSearch = async () => {
const res = await instance.get(category.search + searchQuery);
console.log(res.data.results);
const searchData = res.data.results;
setSearchList(searchData);
};
검색할 URL의 예시는 다음과 같습니다.
3. input 태그의 value를 query로 전달하도록 합니다.
매 타이핑마다 데이터를 불러오는 것을 피하기 위해서 setTimeout()을 이벤트에 주었습니다.
0.5초간 기다린 뒤에 실행하여 데이터를 불러오도록 합니다.
// 검색어를 입력할 때마다 바꾸지 않고 입력하고 잠깐 기다렸다가 출력되도록 하려면 이벤트에 setTimeout을 합니다.
const querySetTimeout = (e) => {
setTimeout(() => {
setSearchQuery(e.target.value);
}, 500);
};
4. useEffect를 이용하여 query의 값이 변하면 검색결과를 출력하도록 합니다.
검색어를 다 지웠을 때 검색 결과가 남지 않도록 if문을 이용하여 검색창이 비어있다면 searchList를 비우도록 합니다.
const SearchMovie = ({ searchVisual, TRENDINGDATA, getTMDBSearch, searchList, setSearchList, searchQuery, setSearchQuery }) => {
useEffect(() => {
// input이벤트는 onChange로 검색어가 변할 때마다 검색결과를 출력하도록 합니다.
if (searchQuery !== "") {
getTMDBSearch();
// 검색창이 비어있다면 검색결과를 삭제합니다.
} else if (searchQuery === "") {
setSearchList([]);
}
}, [searchQuery]);
5. slice() 메서드를 이용하여 인기 영화 순으로 5개의 영화를 그리도록 합니다.
<h3>예매율 순위</h3>
<div className="content">
<ul className="left">
{TRENDINGDATA.slice(0, 5).map((el, idx) => {
return (
6. onMouseEnter 이벤트를 이용해서 마우스를 타이틀에 가져다 댈 경우 이미지가 나타나도록 합니다.
<li key={idx} className={`${idx === num ? "on" : ""}`}>
<div className="img">
<figure>
</figure>
</div>
<div className="txt">
<p>
<span>{idx + 1}</span>
<strong
onMouseEnter={() => {
setNum(idx);
}}
>
7. 검색 결과창도 동일한 방식으로 출력해줍니다.
너무 많은 결과가 나와 css를 깨지 않도록 하기 위해서 마찬가지로 slice() 메서드를 이용해 7개까지만 출력하도록 합니다.
<ul className="right">
<input onChange={(e) => querySetTimeout(e)} placeholder="영화이름으로 검색하세요. ex) 토르" />
{searchList.slice(0, 7).map((el, idx) => {
return (
8. 이미지가 존재하지 않는 데이터가 있습니다.
검색결과 품질을 높이기 위해 이미지가 존재하지 않는 경우는
상함연산자를 이용하여 해당 데이터를 검색 결과에서 제외하도록 했습니다.
return (
<li key={idx} className={`${idx === sNum ? "on" : ""}`}>
{el.poster_path ? (
<div className="autoComp">
<div className="txt">
<span
onMouseEnter={() => {
setSNum(idx);
}}
>
{el.title}
</span>
</div>
<div className="img">
</div>
</div>
) : (
""
)}
</li>