사고쳤어요
[React / ts] Book Store 만들기 - ⑧ 쿼리스트링을 활용한 BooksFilter 구현 본문
쿼리스트링을 활용하여 BooksFilter를 구현하여 카테고리를 선택하였음을 알 수 있도록 해보자.
// BooksFilter.tsx
import styled from "styled-components";
import { useCategory } from "../../hooks/useCategory";
import Button from "../common/Button";
import { useSearchParams } from "react-router-dom";
const BooksFilter = () => {
const { category } = useCategory();
const [searchParams, setSearchParams] = useSearchParams();
const handleCategory = (id: number | null) => {
const newSearchParams = new URLSearchParams(searchParams);
if (id === null) {
newSearchParams.delete("category_id");
} else {
newSearchParams.set("category_id", id.toString());
}
setSearchParams(newSearchParams);
};
const handleNews = () => {
const newSearchParams = new URLSearchParams(searchParams);
if (newSearchParams.get("news")) {
newSearchParams.delete("news");
} else {
newSearchParams.set("news", "true");
}
setSearchParams(newSearchParams);
};
return (
<BooksFilterStyle>
<div className="category">
{category.map((item) => (
<Button
size="medium"
scheme={item.isActive ? "primary" : "normal"}
key={item.category_id}
onClick={() => {
handleCategory(item.category_id);
}}
>
{item.category_name}
</Button>
))}
</div>
<div className="new">
<Button
size="medium"
scheme={searchParams.get("news") ? "primary" : "normal"}
onClick={handleNews}
>
신간
</Button>
</div>
</BooksFilterStyle>
);
};
const BooksFilterStyle = styled.div`
display: flex;
gap: 24px;
margin-bottom: 10px;
.category {
display: flex;
gap: 8px;
}
`;
export default BooksFilter;
URLSearchParams는 URL의 쿼리 문자열을 다루기 위한 Web API로 브라우저에서 ?key=value 형식의 URL 파라미터를 읽고, 수정하고, 추가하거나 삭제할 수 있게 해주는 객체이다.
예를 들어 newSearchParams라는 URLSearchParams가 존재할 때
newSearchParams.set("id", 1)을 실행하면 기존 URL에 id=1이 추가된다.
이를 바탕으로 카테고리 버튼이 클릭될 떄 handleCategory를 통해
category id가 null인 경우에는 newSearchParams.delete()를 통해 category_id를 제거해주었고
category id가 존재하는 경우에는 newSearchParams.set()을 통해 category_id를 추가해주었다.
// useCategory.ts
import { useEffect, useState } from "react";
import { Category } from "../models/category.model";
import { fetchCategory } from "../api/category.api";
import { useLocation } from "react-router-dom";
export const useCategory = () => {
const [category, setCategory] = useState<Category[]>([]);
const location = useLocation();
const setActive = () => {
const params = new URLSearchParams(location.search);
if (params.get("category_id")) {
setCategory((prev) => {
return prev.map((item) => {
return {
...item,
isActive: item.category_id === Number(params.get("category_id")),
};
});
});
} else {
setCategory((prev) => {
return prev.map((item) => {
return {
...item,
isActive: false,
};
});
});
}
};
useEffect(() => {
fetchCategory().then((category) => {
if (!category) return;
const categoryWithAll = [
{
category_id: null,
category_name: "전체",
},
...category,
];
setCategory(categoryWithAll);
setActive();
});
}, []);
useEffect(() => {
setActive();
}, [location.search]);
return { category };
};
선택된 카테고리를 확인할 수 있도록 isActive라는 속성을 추가한 useCategory이다.
useLocation()과 URLSearchParams를 활용하여 현재 URL의 파라미터를 불러오고,
그 파라미터의 category id와 버튼의 category id가 일치하는 경우 isActive를 true로 설정해준다.
'웹 풀스택' 카테고리의 다른 글
[React / ts] Book Store 만들기 - ⑩ 주문 처리(주소 검색 구현) (0) | 2025.04.28 |
---|---|
[React / ts] Book Store 만들기 - ⑨ 도서 상세 페이지 제작 (0) | 2025.04.24 |
[React / ts] Book Store 만들기 - ⑦ Zustand를 활용한 로그인 구현 (0) | 2025.04.23 |
[React / ts] Book Store 만들기 - ⑥ Axios 사용과 웹서버 연결 (1) | 2025.04.21 |
[React / ts] Book Store 만들기 - ⑤ 라우터 만들기 (0) | 2025.04.21 |