티스토리 뷰
이번 팀 프로젝트 주제는 마켓컬리와 같은 식품 쇼핑몰로 정해졌다
카테고리 버튼을 클릭하여 상품 리스트 페이지에 들어가면 상품 데이터들이 높은 가격 기준으로 정렬된 상태로 가져와야하는데 상품 등록 시 상품 가격 타입을 number로 넣었지만 파이어베이스에서 문자열로 변환되어 등록되어 버린다 문자인 상태에서 orderBy로 정렬하게 되면 유니코드로 정렬이 되기 때문에 원하는 정렬 기준을 맞출 수 없다는 문제가 발생했다
내가 하고자 하는 것
상품 가격을 기준으로 오름, 내림 차순을 만들고 싶다
문제해결을 위해 시도한 방법
- 파이어베이스로 전체 데이터를 불러온 뒤 sort를 이용해 정렬해 줬다
- 이 방법으로 정렬은 가능하지만 클라이언트가 아닌 서버에서 요청값에 정렬을 요청해서 받아야 한다는 피드백을 받고 다시 수정하기로 했다
{products?.sort((a,b)=>b.price-a.price).map((item) => {
return (
<div key={item.productId} className="w-1/4 p-5">
<div className="h-full flex flex-col justify-between items-center ">
<img
src={item.image}
alt="상품이미지"
className="w-4/5 h-80 object-cover rounded-md hover:scale-95 transition-all duration-300 cursor-pointer"
/>
<button className="w-4/5 mt-3 bg-slate-100 flex justify-center items-center text-black py-2 px-4 hover:bg-white rounded-md">
<span className="text-xl">담기</span> <LiaCartArrowDownSolid className="ml-2 text-3xl" />
</button>
<div className="pt-2 w-4/5">
<p className="text-lg font-semibold">{item.title}</p>
<div className="flex justify-between items-center mt-2">
<div>
<p className="text-lg font-semibold">{item.price ? stringTransform(item.price) : null} 원</p>
</div>
<div className="flex gap-2 items-center">
{heart ? (
<IoHeartSharp onClick={handleHeart} className="text-3xl text-rose-500 cursor-pointer" />
) : (
<IoHeartSharp onClick={handleHeart} className="text-3xl hover:text-rose-500 cursor-pointer" />
)}
</div>
</div>
</div>
</div>
</div>
);
})}
문제해결!
- 파이어베이스 공식 문서를 보면 인구수를 기준으로 orderBy를 이용해 정렬하는데 문자로 등록이 된다는 게 아무래도 이상해서 다시 확인해 보기로 했다
- input type도 number이고, formData type도 number로 잘 넣어줬는데 왜 여기서 문자로 변형되어 등록되는 걸까?
- 결국 이유는 formData 때문이었다. const price = formData.get('price') as number 여기에서 type를 number로 넣어줘도 formData.get 때문에 문자로 변환되기 때문이다
- 명시성을 위해 price = formData.get('price') as number => string 으로 바꿔주고 등록 객체에서 number로 형 변환 후 등록해 주니 파이어베이스에서도 숫자로 등록된 걸 확인할 수 있었다
- 상품 가격이 문자로 들어가서 문제였던 부분이 해결되었으니 파이어베이스에서 데이터요청 쿼리에 selectedTab state 값에 따라 정렬 쿼리를 다르게 받고 selectedTab가 바뀔 때마다 데이터를 새로 요청할 수 있도록 의존성 배열에도 담아주면 정렬기능 완성
등록 폼 수정
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsSubmitting(true);
const key = uuidv4();
const storageRef = ref(storage, key);
const formData = new FormData(e.currentTarget);
const category = formData.get('category') as string;
const title = formData.get('title') as string;
const info = formData.get('info') as string;
const delivery = formData.get('delivery') as string;
const seller = formData.get('seller') as string;
const price = formData.get('price') as string;
const weight = formData.get('weight') as string;
console.log('확인', typeof price);
try {
let image = '';
if (imageUrl) {
const data = await uploadString(storageRef, imageUrl, 'data_url');
image = await getDownloadURL(data?.ref);
}
const newProduct = {
productId: uuidv4(),
image,
category,
title,
info,
delivery,
seller,
price: Number(price),
weight,
createdAt: new Date()?.toLocaleString(),
quantity: 1
};
await addDoc(collection(db, 'product'), {
...newProduct
});
toast?.success('상품이 등록되었습니다.');
(e.target as HTMLFormElement).reset();
setImageUrl('');
} catch (error: any) {
console.log(error);
toast?.error(error.code);
}
setIsSubmitting(false);
};
데이터 정렬 요청
const [selectedTab, setSelectedTab] = useState(true);
const [products, setProducts] = useState<ProductType[]>([]);
useEffect(() => {
const fetchProductsData = async () => {
try {
const querySnapshot = await getDocs(
selectedTab
? query(collection(db, 'product'), orderBy('createdAt', 'desc'))
: query(collection(db, 'product'), orderBy('createdAt', 'asc'))
);
const fetchedProducts: any[] = [];
querySnapshot.forEach((doc) => {
const products = doc.data();
fetchedProducts.push({ ...products, id: doc.id, products });
});
setProducts(fetchedProducts);
} catch (error) {
console.log('상품 데이터 가져오기 실패', error);
}
};
fetchProductsData();
}, [selectedTab]);
'TIL > Next' 카테고리의 다른 글
[넥스트 Next.js] 쇼핑몰 프로젝트_파이어베이스 , 리액트쿼리 제대로 알기 (0) | 2024.03.22 |
---|---|
[넥스트 Next.js] 쇼핑몰 프로젝트_상품 데이터 리액트 쿼리 (React Query) 사용하기 (0) | 2024.03.21 |
[넥스트 Next.js] 라우팅을 이해하기 위한 주요 용어, 페이지 이동 기능 (0) | 2024.03.13 |
[넥스트 Next.js] 라우터 (Router) 주요 렌더링 기법 (0) | 2024.03.13 |
[넥스트 Next.js] 설치 명령어, 코드스플리팅 (Code Splitting) (0) | 2024.03.12 |