홈페이지 검색창에 검색어를 입력 후 검색 버튼을 클릭할 경우
ProductList페이지로 이동하여 검색 결과를 출력하도록 함
Navbar.jsx
useState 로 search를 추가한다.
검색창(input)의 내용이 변경될 때마다 setSearch로 검색어를 저장한다.
그리고 onSubmit 이벤트로 검색 버튼을 클릭할 경우
handleSubmit을 실행하여
검색어가 공백이 아닐 경우에만 navigate를 사용해 products로 이동한다.
파라미터로는 search= 검색어에 공백을 제거해서 보낸다.
const Navbar = ({ user, cartCount }) => {
const [search, setSearch] = useState(""); //검색어
const navigate = useNavigate();
// 검색 버튼 클릭 시 실행
// 검색어가 공백이면 실행안되게 하며, 검색어가 있을 경우 공백 제거 후 동작
const handleSubmit = (e) => {
e.preventDefault();
if (search.trim() !== "") {
navigate(`/products?search=${search.trim()}`);
}
};
return (
<nav className="align_center navbar">
<div className="align_center">
<h1 className="navbar_heading">myCart</h1>
<form onSubmit={handleSubmit} className="align_center navbar_form">
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
className="navbar_search"
placeholder="제품 찾기..."
/>
<button type="submit" className="search_button">
검색하기
</button>
</form>
</div>
ProductsPage.jsx에서 검색어를 파라미터로 받아서 사용할거다.
searchQuery 로 search 파라미터를 받아온다.
그리고 useData로 데이터를 받아올 때 검색어를 파라미터로 추가하여서 보내고
[searchQuery]가 변경되면 실행되게끔 추가한다.
const ProductsList = () => {
//sidebar에서 카테고리 쿼리스트링을 받아온다.
const [search, setSearch] = useSearchParams();
const category = search.get("category"); //모든 쿼리스트링 중 카테고리
const searchQuery = search.get("search"); //검색창에서 검색어 가져오기
const page = search.get("page");
//useDate(url)이 들어가야함
//결과(res)는 categories와, error에 담는다.
const { data, error, isLoading } = useData(
"/products",
{
params: {
search: searchQuery, //검색어 추가
category, //카테고리 파라미터 전달
page, //페이지 추가(페이지네이션 사용)
},
},
[searchQuery, category, page]
);
ProductsList.jsx
상품 리스트 페이지에 정렬 옵션을 추가할거임
정렬 방법과 정렬 결과를 관리할 useState를 추가한다.
const ProductsList = () => {
const [sortBy, setSortBy] = useState(""); //정렬 방법
const [sortedProducts, setSortedProducts] = useState([]); //정렬 결과
그리고 select 태그에 onChange 이벤트로
select의 옵션이 변경될 때 마다 setSortBy 에 바뀐 정렬 옵션을 저장한다.
<h2>상품목록</h2>
<select
onChange={(e) => setSortBy(e.target.value)}
name="sort"
id=""
className="products_sorting"
>
<option value="">정렬방법</option>
<option value="price desc">가격높은순</option>
<option value="price asc">가격낮은순</option>
<option value="rate desc">평점높은순</option>
<option value="rate asc">평점낮은순</option>
</select>
//정렬하기
useEffect(() => {
//데이터와 데이터 안의 제품이 있을 경우(useData의 결과)
if (data && data.products) {
// 데이터의 products를 복사하여 products함수에 담는다.
const products = [...data.products];
if (sortBy === "price desc") {
//sortBy(정렬 옵션)이 가격 내림차순
setSortedProducts(products.sort((a, b) => b.price - a.price));
} else if (sortBy === "price asc") {
//sortBy(정렬 옵션)이 가격 오름차순
setSortedProducts(products.sort((a, b) => a.price - b.price));
} else if (sortBy === "rate desc") {
//sortBy(정렬 옵션)이 평점 내림차순
setSortedProducts(
products.sort((a, b) => b.reviews.rate - a.reviews.rate)
);
} else if (sortBy === "rate asc") {
//sortBy(정렬 옵션)이 평점 오름차순
setSortedProducts(
products.sort((a, b) => a.reviews.rate - b.reviews.rate)
);
} else {
//정렬 옵션이 그 외의 경우 (default)
setSortedProducts(products);
}
}
}, [sortBy, data]); //정렬방법과 데이터가 바뀔 때 마다 실행
products.sort((a,b) => b.price = a.price));
((a,b) => b.price = a.price)); 이 부분이 정렬 조건임
b의 가격에서 a의 가격을 마이너스 했을 때 참이면 앞에 온다.
https://hianna.tistory.com/409
그리고 정렬된 결과를 반복문으로 출력한다.
{/* products가 있을 경우 반복문으로 출력 */}
{data.products &&
sortedProducts.map((product) => (
<ProductCard key={product._id} product={product} />
))}
1. default
2. 가격 높은 순
3. 평점 낮은 순
등 정렬이 가능하다.
하지만 여기서 문제는...
이 정렬이 각 페이지에서만 가능하다는 점
이 부분의 개선이 필요하다
useEffect(() => {
if (user) getCart(); // 유저가 바뀌거나 시작 시 카트 정보 가져온다.
}, [user]);