[Day58] CartPage
[Day58] CartPage
CartPage
전체 흐름
사용자가 /cart 경로로 진입
- Router에서 cartPageLoader 실행
- cartPageLoader에서 getCartData 호출
- getCartData가 axios로 백엔드 API 요청
- 응답 데이터를 받아 cartItems로 반환
- 반환된 cartItems가 CartPage 컴포넌트에 전달됨
Router 설정 router.jsx
1
{ path: '/cart', element: <CartPage />, loader: cartPageLoader },
cartPageLoader
가 실행되어 초기 데이터를 미리 로드CartPage
컴포넌트가 해당 데이터를 받아 렌더링
cartPageLoader
1
2
3
4
5
6
7
8
9
10
11
export const cartPageLoader = async () => {
try {
const cartItems = await getCartData()
if (!cartItems || cartItems.length === 0) {
return { cartItems: [] }
}
return cartItems
} catch (err) {
console.log('err', err)
}
}
getCartData
함수 호출 → 장바구니 데이터를 비동기적으로 요청- 응답 받은 데이터가 없거나 빈 배열이면 빈 객체 반환
- 그 외에는 그대로
cartItems
반환
getCartData (API 호출 함수)
1
2
3
4
5
6
7
8
export const getCartData = async () => {
try {
const res = await axios.get(`/api/cart/`)
return res.data
} catch (err) {
console.log('err', err)
}
}
/api/cart/
경로로 GET 요청- 응답 데이터를 그대로 반환 (
res.data
)
기능
- 장바구니 페이지에서 총 수량 및 총 금액 표시
- 상품 수량 조절, 상품 삭제
- 백엔드와 통신하여 장바구니 정보 수정 (GET, PUT, DELETE)
🔹 총 수량 및 금액 계산
1
2
3
4
5
6
7
// 장바구니 총 수량 계산 reduce 고차함수
const totalCount = items.reduce((sum, item) => sum + item.count, 0)
// 총 계산할 금액
const totalSum = items.reduce(
(sum, item) => sum + Math.round(item.price * item.count * (1 - item.discount / 100)),
0
)
- reduce 사용해서 수량, 금액 계산
- 할인율(discount) 고려해 계산
🔹 수량 증가: increase(id)
1
2
3
4
5
6
7
8
9
10
const increase = id => {
// 아이템이 없으면 일찍 함수 종료
const currentItem = items.find(item => item.id === id)
if (!currentItem) return
setItems(prev => prev.map(item => (item.id === id ? { ...item, count: item.count + 1 } : item)))
const newCount = items.find(item => item.id === id).count + 1
// cartApi에 업데이트 요청
updateCartItemCount(id, newCount).catch(err => console.log('err', err)) // 에러처리 추가;
}
- 로컬 state에서 먼저 수량 증가
- 변경된 수량을
cartApi.js
의updateCartItemCount
로 서버에 반영 (PUT)
1
2
3
4
5
6
7
8
9
10
export const updateCartItemCount = async (id, count) => {
try {
const cartItem = await axios.get(`/api/cart/${id}`)
const updateItem = { ...cartItem.data, count }
const res = await axios.put(`/api/cart/${id}`, updateItem)
return res.data
} catch (err) {
console.log('err', err)
}
}
GET
으로 기존 데이터 받아온 뒤count
만 수정해서PUT
요청
🔹 수량 감소: decrease(id)
1
2
3
4
5
6
7
8
9
10
11
12
const decrease = id => {
const currentItem = items.find(item => item.id === id)
if (!currentItem) return
setItems(prev =>
prev.map(item =>
item.id === id && item.count > 1 ? { ...item, count: item.count - 1 } : item
)
)
const newCount = items.find(item => item.id === id).count - 1
if (newCount >= 1) updateCartItemCount(id, newCount).catch(err => console.log('err', err))
}
- 수량이 1 이하가 되지 않도록 제한
- 서버에도 동일하게 갱신 요청
🔹 아이템 삭제
1
2
3
4
5
6
const hadleDelete = id => {
if (window.confirm('정말 삭제하시겠습니까?')) {
setItems(prev => prev.filter(item => item.id !== id))
removeFromCart(id)
}
}
- 삭제 전 confirm으로 사용자 확인
- 삭제 후 로컬 상태와 서버 모두 갱신 (DELETE 요청)
1
2
3
4
5
6
7
8
export const removeFromCart = async id => {
try {
const res = await axios.delete(`/api/cart/${id}`)
return res.data
} catch (err) {
console.log('err', err)
}
}
장바구니 페이지
END
This post is licensed under CC BY 4.0 by the author.