handleAddToCart
const handleAddToCart = (item) => {
setCartItem((prev) => {
const existItem = prev.find((i) => i.id === item.id);
if (existItem) {
return prev.map((i) =>
i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
);
} else {
return [...prev, { ...item, quantity: 1 }];
}
});
};
먼저 장바구니 기능을 위한 handleAddToCart 함수이다.
const existItem = prev.find((i) => i.id === item.id);
조건문에서 활용될 existItem 변수
기존( prev )에 이미 장바구니에 있는 상품이라면
(전달 받은 매개변수 item의 id와 기존 상품 id를 비교한다.)
기존 quantity 상태에서 + 1을 추가를 한다.
기존 장바구니에 없는 아이템이라면 quantity를 1로 설정을 한다.
Content 컴포넌트 전체 코드
import "../../resources/content/content.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBasketShopping } from "@fortawesome/free-solid-svg-icons"; // 장바구니 아이콘
import { useNavigate } from "react-router-dom";
import axios from "axios";
import { useEffect, useState } from "react";
/** 구조분해를 통해서 onAddToCart라는 props 할당한다. */
/**
구조분해를 안한다면 아래 처럼 접근을 해야한다.
function Content(props) {
const onAddToCart = props.onAddToCart;
*/
export default function Content({ onAddToCart }) {
const [products, setProducts] = useState([]);
useEffect(()=>{
const fetchProducts = async()=>{
try{
const res = await axios.get(`http://localhost:3001/products`)
setProducts(res.data);
}catch(e){
console.error(e + '상품 목록 불러오기 실패');
}
}
// 비동기 함수 호출
fetchProducts();
}, [])
const navigator = useNavigate();
/** product: 사용자가 클릭한 상품 객체 (map에서 반복 중인 item이 전달됨)
onAddToCart(product): 부모(App)에서 전달받은 장바구니 추가 함수 실행
*/
const handlebasketClick = (product) => {
onAddToCart(product);
if (window.confirm("장바구니로 이동하시겠습니까?")) {
navigator("/cart");
}
};
return (
<div className="content-area">
{products.map((item) => (
<div className="content-item" key={item.id }>
<a href="">
<img
src={item.image.startsWith('http') ? item.image : process.env.PUBLIC_URL + item.image}
alt={item.name}
/>
</a>
<p>{(item.price).toLocaleString()}원</p>
<p>
{item.name}
<button className="basketBtn"onClick={() => handlebasketClick(item)}>
<FontAwesomeIcon
className="basket-icon"
icon={faBasketShopping}
/>
</button>
</p>
<p>{item.description}</p>
</div>
))}
</div>
);
}
const handleAddToCart = (item) => {
setCartItem((prev) => {
const existItem = prev.find((i) => i.id === item.id);
if (existItem) {
return prev.map((i) =>
i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
);
} else {
return [...prev, { ...item, quantity: 1 }];
}
});
};
const [products, setProducts] = useState([]);
상품의 목록을 상태로 저장하고 보여주기 위한 products useState();이다.
useEffect() :: 컴포넌트가 처음 화면에 렌더링될 때 한 번만 실행되도록 한다.
[] 빈 배열 상태로 최초로 1회만 실행이 된다.
useEffect(()=>{
const fetchProducts = async()=>{
try{
const res = await axios.get(`http://localhost:3001/products`)
setProducts(res.data);
}catch(e){
console.error(e + '상품 목록 불러오기 실패');
}
}
// 비동기 함수 호출
fetchProducts();
}, [])
axios.get()은 네트워크 요청으로 비동기 작업이다.
axios.get() [조회]을 통해서 json-server 안에 있는 products 데이터를 꺼내 온다.
res.data 안에 배열 형태로 데이터가 들어있다 이 부분은 console.log로 통해서
axios.get() 으로 받은 res 안에 무슨 형태로 데이터들이 넘어 온지 확인이 가능하다.
서버에서 가져온 데이터를 serProducts로 상태를 업데이트한다.
함수 호출을 통해서 컴포넌트가 처음 렌더링될 때 상품 데이터를 가져온다.
await를 쓰기 위한 async 함수로 정의를 한다.
try ~ catch를 통해서 예외처리를 한다.
<div className="content-area">
{products.map((item) => (
<div className="content-item" key={item.id }>
<a href="">
<img
src={item.image.startsWith('http') ? item.image : process.env.PUBLIC_URL + item.image}
alt={item.name}
/>
</a>
<p>{(item.price).toLocaleString()}원</p>
<p>
{item.name}
<button className="basketBtn"onClick={() => handlebasketClick(item)}>
<FontAwesomeIcon
className="basket-icon"
icon={faBasketShopping}
/>
</button>
</p>
<p>{item.description}</p>
</div>
))}
</div>
);
products.map((item)
useState를 통해서 받아온 데이터를 배열에 있는 모든 상품을 반복해서 출력한다.
숫자를 쉼표(,) 단위로 포맷 (ex: 15000 → 15,000) |