export const apis:{searchProduct: (page, data) => api.get(`products/?page=${page}&search=${data}`)}
//Search.js
const location = useLocation();
const [page, setPage] = useState(1);
const [list, setList] = useState([]);
const [searchList, setSearchList] = useState([]);
useEffect(() => {
apis.searchProduct(page, location.state.search)
.then((res) => {
if (page < Math.ceil(res.data.count / 15)) {
setPage((p) => p + 1)
setList((p) => p.concat(res.data.results))
}
const filterList = list.filter((p) => p.product_name.toLocaleLowerCase().includes(location.state.search.toLocaleLowerCase()))
setSearchList(filterList)
})
.catch((error) => {
console.log("서치에러", error)
})
}, [location.state.search, page])
return (
<div>
{userType === "SELLER" ?
<Nav />
:
<Nav user_nav children={isLogin ? "마이페이지" : "로그인"} />
}
<SearchGrid searchList={searchList} />
</div>
)
}
export default Search
위의 api주소로 데이터 요청을 보내야 하기 때문에 Search 컴포넌트에서 useEffect로 api요청을 보낸다. 검색 api는 데이터가 페이지별로 15개씩 나눠져있기 때문에 데이터 요청을 보낼 때, 어떤 페이지의 데이터를 필요로 하는지 페이지 데이터와(page), 어떤 단어가 포함된 검색어인지에 대한 검색어 데이터(location.state.search)를 함께 보내서 데이터를 요청해야 한다.
이렇게 응답 받아온 데이터 res.data에는 count로 총 데이터가 몇개 담겨있는지 표기되어 있고, results에는 현제 페이지의 api주소에 15개의 데이터가 담겨져있다고 표기되어 있다. 이를 사용해서 몇페이지까지의 데이터를 가져올지에 대한 조건식을 세워줄 수 있다 (page < Math.ceil(res.data.count / 15))이렇게 Math.ceil은 소수점 이하를 올림 해주는 함수로 마지막 페이지는 15개의 데이터가 꽉 차있지 않을 수도 있기 때문에 올림 함수를 사용해준다. 그래서 총 카운트 70에 15개를 나눈 만큼의 수 (70/15) 4.6에서 올림한 5페이지까지가 되기 전까지 setPage((p) => p + 1)을 해주고 5페이지 까지의 데이터를 list 배열에 모두 담아준다.(setList((p) => p.concat(res.data.results)))
list 배열에서 filter 함수를 사용해 받아온 데이터의 product_name중에 검색어(location.state.search)가 포함되어 있는 데이터를 걸러준다. 이때는 filter 함수 안에서 inclueds 함수를 사용해서 분별해준다. 그리고 toLocaleLowerCase 메소드를 사용해 문자를 소문자로 변형시켜줘서 검색어를 입력할 때 소문자와 대소문자 상관없이 해준다.
검색어가 포함된 데이터 배열을 filterList라는 변수에 담았고 이 변수를 setSearchList에 담아줘서 searchList를 통해 map을 돌려 화면에 이 데이터들이 표시되게끔 해준다.
// SearchGrid.js
function SearchGrid({ searchList }) {
return (
<Container>
{searchList.map((p) => {
return <div key={p.product_id}>
<img src={p.image} alt="" />
<p className='product-name'>{p.store_name}</p>
<p className='product'>{p.product_name}</p>
<span className='product-price'>{p.price}</span>
<span>원</span>
</div>
})}
</Container>
)
}
onkeydown, onkeyup, onkeypress 이벤트는 키보드 입력시 동작 시점에 따라 발생하는 키보드 이벤트 이다.
그중에서
onKeyUp 이벤트는 키를 눌렀다가 뗐을 때 이벤트이다. 이 이벤트를 사용해서 Enter Key로도 검색어를 검색할 수 있다.
const handleSearchEnter = (e) => {
if (e.key === "Enter") {
handleSearch()
console.log(e)
}
}
const handleSearch = (e) => {
navigate(`/search?query=${search}`, {
state: {
search
}
})
}
<Input
nav_input
placeholder="상품을 검색해보세요!"
defaultValue={props.search}
_onChange={(e) => setSearch(e.target.value)}
_onClick={handleSearch}
_onKeyUp={(e) => handleSearchEnter(e)}
/>