카테고리 없음

1.React json-Server 활용 프로젝트 애견용품샵 만들기(Haechan_Pet_Shop) products content 컴포넌트 만들기

최종군 2025. 7. 4. 00:24

 

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 안에 무슨 형태로 데이터들이 넘어 온지 확인이 가능하다. 

   setProducts(res.data);

서버에서 가져온 데이터를 serProducts로 상태를 업데이트한다. 

    fetchProducts();

함수 호출을 통해서 컴포넌트가 처음 렌더링될 때 상품 데이터를 가져온다. 

 

 

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를 통해서 받아온 데이터를 배열에 있는 모든 상품을 반복해서 출력한다. 

 

.toLocaleString()

 

숫자를 쉼표(,) 단위로 포맷 (ex: 15000 → 15,000)