상품을 업로드 할 때 카테고리를 선택하는 기능을 추가했다. 홈 화면에서 카테고리를 골라서 보는 기능을 추가하는 도중에 좀 헷갈렸던 것들을 기록해보자.
일단 홈 화면
📂index.tsx
const [seleted, setSelected] = React.useState<string>("");
const { data } = useSWR<ProductsResponse>("/api/products");
return(
<Layout title="Home" hasTabBar>
<CategoryNav setSelected={setSelected} />
)
api/products에서 data를 가져오는 곳에 선택한 값을 전달하고 싶어서 query string으로 전달하려고 코드를 수정했다. 이걸 역순서로 진행해서 홈화면을 가장 뒤늦게 수정해서 더 헷갈린거같다.
<const { data } = useSWR<ProductsResponse>(`/api/products?categoryQuery=${seleted}`);
그 다음 CategoryNav 컴포넌트에서 헤맸는데, Nav 안에 CategoryBox 컴포넌트를 이용중이었다. CategoryBox가 각각 카테고리들이고, 선택하면 onClick으로 선택한 값을 Nav로 전달하고, Nav는 그 값을 useState로 만든 setPath에 저장했다. 이제 이것을 홈 화면으로 옮겨야 하는데..!
setPath로 바꾼 값 path를 홈으로 전달하면 된다. 어 왜 안되지? 상태관리를 안쓰고 있고 props로 여러번 이용한 적이 적어서 헤맸다...
const CategoryNav = ( setSelected ) 왜안됨??? 이런실수 그만..!
그렇게 다시 수정한 코드.
📂CategoryNav.tsx
const CategoryNav = ({ setSelected }: { setSelected: (path: string) => void }) => {
const [path, setPath] = React.useState<string>("");
useEffect(() => {
setSelected(path);
}, [path]);
return (
<div className="grid grid-cols-6">
{categoryList.map((item) => (
<div key={item.label} className="col-span-1 p-2 mb-2">
<CategoryBox
onClick={(categoryPath: string) => setPath(categoryPath)}
selected={path === item.path}
name={item.name}
path={item.path}
/>
</div>
))}
</div>
);
};
onClick={(categoryPath: string) => setPath(categoryPath)}뭔가 좀 복잡하다.
useEffect를 안쓰고싶어졌다.
코드 수정!
📂CategoryNav.tsx
const [path, setPath] = React.useState<string>("");
const handleCategoryClick = (categoryPath: string) => {
setPath(categoryPath);
setSelected(categoryPath);
};
return (
<CategoryBox
onClick={() => handleCategoryClick(item.path)}
)
이제 홈 화면에서 query string으로 전달한 값을 백엔드에서 받아서 처리해보자!
📂api/products
// item.findMany 로 category 일치하는 item 찾기
if (req.method === "GET") {
const {
query: { categoryQuery },
} = req;
const seletedCategory = await client.item.findMany({
where: {
category: {
equals: categoryQuery as string,
},
},
});
res.json({
ok: true,
seletedCategory,
});
}
category: {category: categoryQuery}가 안되서 알아보니, 타입오류였다. categoryQuery가 string | string[] | undefined 의 타입이고 prisma의 category는 string이어서 그렇다.
prisma는 equals 필터를 제공한다. category와 categoryQuery의 타입을 비교하고 일치하는 아이템을 찾게 해준다!
그래도 뒤에 as string이 붙어야 했다.
category: categoryQuery as string는 계속 타입오류가 난다.
강의를 보면서 흐름을 따라가는건 좋지만, 역시 직접 코드를 안쳐보고선 늘 수 없는것같다.
어느정도 따라가더라도 방법을 고민하고 원하는 방식으로 안되고, 그 이유를 찾다보면 몇시간씩 훌쩍 지나가버리지만... ㅜ,ㅜ
앞단에서 받아온 categoryQuery로 prisma에서 where에 넣는게 좀 복잡하다고 느꼈다. 이렇게 하는 대신 다른 방법이 있었다!
const {
query: { categoryQuery },
} = req;
let query: any = {};
if (categoryQuery) {
query.category = categoryQuery;
const seletedCategoryProducts = await client.item.findMany({
// 중략
where: query, // 깔끔.
orderBy: {
createAt: "desc",
},
})
이게 훨씬 깔끔하고 편한 것 같다.