[돌멩이] props로 데이터 주고받고 prisma로 찾기

김선은·2023년 10월 27일

상품을 업로드 할 때 카테고리를 선택하는 기능을 추가했다. 홈 화면에서 카테고리를 골라서 보는 기능을 추가하는 도중에 좀 헷갈렸던 것들을 기록해보자.

클라이언트 코드

일단 홈 화면

📂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>
  );
};
  • 제일 앞단에서 useState로 만든 setSelected를 CategoryNav props로 보낸다.
  • CategoryNav({setSelected}) 받아온다
  • onClick props로 받아온 값을 setPath에 넣는다.
    onClick={(categoryPath: string) => setPath(categoryPath)}
  • useEffect로 변화를 확인하고 setSelected에 넣는다.

뭔가 좀 복잡하다.

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",
    },
})

이게 훨씬 깔끔하고 편한 것 같다.

profile
기록은 기억이 된다

0개의 댓글