wecode 1차 클론 프로젝트 React를 사용하여 구현한 장바구니 기능 풀이
핵심 기능 한 줄 설명
useEffect,fetch로 api로 부터 데이터를 받아와 useState로 저장
상품 리스트별로 컴포넌트화하기
상품데이터의 수량이 변화거나 삭제될때, 저장돤 데이터 업데이트
결제하기 누를 시 업데이트 된 데이터 서버에 전송
코드
import { useEffect, useState } from 'react';
import Product from './Product/Product';
import './Cart.scss';
const Cart = () => {
const [productData, setProductData] = useState([]);
let totalSumPrice = 0;
const deletedList = e =>
setProductData(
productData.filter(product => product.id !== Number(e.target.id))
);
const goToPay = () =>
fetch('api주소', {
method: 'POST',
headers: {
'content-Type': 'application/json',
},
body: JSON.stringify({
productData: productData,
}),
});
const productList = productData.map((product, idx) => {
totalSumPrice += product.price * product.count;
return (
<Product
key={idx}
id={product.id}
idx={idx}
name={product.name}
size={product.size}
count={product.count}
price={product.price}
deletedList={deletedList}
productData={productData}
setProductData={setProductData}
/>
);
});
useEffect(() => {
fetch('data/data.json')
.then(response => response.json())
.then(setProductData);
}, []);
return (
<div className="cart">
{productList.length === 0 ? (
<div className="empty">
<div />
<p>카트가 비어있습니다.</p>
</div>
) : (
<>
<div className="naviLocation">
<div className="titleArea">카트</div>
<div className="sizeArea">사이즈</div>
<div className="countArea">수량</div>
<i className="fi fi-br-cross" />
</div>
{productList}
<div className="cartUnder">
<div className="underArea">
<div className="notice">
<span>전 제품 무료 배송 혜택을 즐겨보세요.</span>
</div>
<div className="price">
<p>소계 (세금 포함)</p>
<span>₩ {totalSumPrice.toLocaleString('ko-KR')}</span>
</div>
<div className="payment">
<button onClick={goToPay}>결제하기</button>
</div>
</div>
</div>
</>
)}
</div>
);
};
export default Cart;
import { useState } from 'react';
import './Product.scss';
const Product = ({
key,
id,
idx,
name,
size,
count,
price,
deletedList,
setProductData,
productData,
}) => {
const sumPrice = price * count;
const [showBtn, setShowBtn] = useState(false);
const [showCount, setShowCount] = useState(true);
const showDelete = () => setShowBtn(true);
const hideDelte = () => setShowBtn(false);
const showCountList = e => {
setShowCount(!showCount);
};
const changeCount = e => {
const newList = productData;
newList[idx].count = Number(e.target.innerText);
setProductData([...newList]);
setShowCount(true);
};
return (
<div className="productLocation" key={key}>
<p className="titleArea">{name}</p>
<p className="sizeArea productArea">{size}</p>
<div
className="countArea btnLocation"
onMouseOver={showDelete}
onMouseLeave={hideDelte}
>
{showCount ? (
<>
<button className="quantity" type="number" onClick={showCountList}>
<p className="btnCount">{count}</p>
<i className="fi fi-rr-angle-small-down" />
</button>
{showBtn && (
<p className="deleteBtn" id={id} onClick={deletedList}>
삭제
</p>
)}
</>
) : (
<ul className="countList" onClick={changeCount}>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
)}
</div>
<p className="price">₩ {sumPrice.toLocaleString('ko-KR')}</p>
</div>
);
};
export default Product;
API로 가져온 데이터 저장
const [productData, setProductData] = useState([]);
useEffect(() => {
fetch('API주소')
.then(response => response.json())
.then(setProductData);
}, []);
상품 리스트별로 컴포넌트화 하기
데이터는 이러한 형태로 받아옵니다.
[
{
"id": 1,
"name": "비 트리플 씨 페이셜 벨런싱 젤",
"size": "60mL",
"count": 2,
"price": 580000
},
{
"id": 2,
"name": "휠 오드 퍼품",
"size": "50mL",
"count": 1,
"price": 145000
},
{
"id": 3,
"name": "레퍼런스 아로마틱 핸드 밤",
"size": "75mL",
"count": 1,
"price": 31000
},
{
"id": 4,
"name": "제라늄 리프 바디 스크럽",
"size": "180mL",
"count": 1,
"price": 43000
}
]
상품리스트를 컴포넌트화 하는 과정에서 'totalSumPrice'라는 총 가격을 구합니다.
let totalSumPrice = 0;
const productList = productData.map((product, idx) => {
totalSumPrice += product.price * product.count;
return (
<Product
key={idx}
id={product.id}
idx={idx}
name={product.name}
size={product.size}
count={product.count}
price={product.price}
deletedList={deletedList}
productData={productData}
setProductData={setProductData}
/>
);
});
상품 리스트 삭제 및, 수량 변동
-- 최상위 컴포넌트
const deletedList = e =>
setProductData(
productData.filter(product => product.id !== Number(e.target.id))
);
-- Product컴포넌트 내부
<p className="deleteBtn" id={id} onClick={deletedList}>
삭제
</p>
Product 컴포넌트 내부
const changeCount = e => {
const newList = productData;
newList[idx].count = Number(e.target.innerText);
setProductData([...newList]);
setShowCount(true);
<ul className="countList" onClick={changeCount}>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
};
결제하기
const goToPay = () =>
fetch('api주소', {
method: 'POST',
headers: {
'content-Type': 'application/json',
},
body: JSON.stringify({
productData: productData,
}),
});
<button onClick={goToPay}>결제하기</button>
마무리
해당 내용은 정답이 아닙니다.
그저 wecode 수강생분들이 '어떻게해야하지' 라는 생각이 들때,
참고 할 수 있도록 불친절하게 풀어 쓴 글이니 오류가 있을 수도 있습니다.
댓글로 남겨주시면 적극 반영 수정 하겠습니다.