FRONTEND/React

[myCart] react-toastify 라이브러리 사용으로 카트 추가 시 메세지 출력

죠으닝 2023. 12. 21. 12:27

$ npm i react-toastify

 

 

App.jsx

// toastify
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

 

상품 추가 및 에러 시 토스트 메세지 출력

    addToCartAPI(product._id, quantity)
      .then((res) => {
        toast.success("상품 추가 성공!"); //toast메세지출력
      })
      .catch((err) => {
        toast.error("상품 추가에 실패했습니다."); //toast메세지출력
      });

 

 

테스트

 

 

 

cartServices에 카트 정보를 가져오는 함수를 추가한다. 

import apiClient from "../utils/api-client";

//카트에 제품 id와 수량을 추가하는 요청
export function addToCartAPI(id, quantity) {
  return apiClient.post(`/cart/${id}`, { quantity });
}

//카트 정보 가져오기
export async function getCartAPI() {
  return await apiClient.get("/cart");
}

 

App.jsx에서 getCart를 로그인한 유저가 바뀔 때 마다 실행한다. 

그리고 setCart에 장바구니의 데이터를 저장한다. 


  //유저가 바뀔 때 마다 그 유저의 장바구니 데이터 가져옴
  const getCart = () => {
    getCartAPI()
      .then((res) => {
        setCart(res.data);
      })
      .catch((err) => {
        toast.error("카트 가져오기에 실패했습니다.");
      });
  };

  useEffect(() => {
    getCart();
  }, [user]);

 

라우팅에 cart의 데이터를 props로 내려주고 

        <Routing addToCart={addToCart} cart={cart} />

 

라우팅에서는 cartPage에 cart 데이터를 내려준다. 


const Routing = ({ addToCart, cart }) => {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/products" element={<ProductsPage />} />
      <Route
        path="/product/:id"
        element={<SingleProductPage addToCart={addToCart} />}
      />
      <Route path="/signup" element={<SignupPage />} />
      <Route path="/login" element={<LoginPage />} />
      <Route path="/cart" element={<CartPage cart={cart} />} />
      <Route path="/myorders" element={<MyOrderPage />} />
      <Route path="/logout" element={<Logout />} />
    </Routes>
  );
};

 

cartPage.jsx에서 cart 데이터를 props로 받아서 사용하면된다.

const CartPage = ({ cart }) => {
  console.log(cart);

 

일단 테스트로 데이터를 잘 받았는지 콘솔로 확인한다. 

 

 

다른 상품 두 개가 들어가있음. 

 

 

이제 이 정보를 받아서 출력하면된다. 

 

map 반복문으로 cart의 길이만큼 상품의 정보를 

 <tbody>
          {cart.map(({ product, quantity }) => (
            <tr key={product._id}>
              <td>{product.title}</td>
              <td>{product.price.toLocaleString("ko-KR")}</td>
              <td className="align_center table_quantity_input">
                <QuantityInput quantity={quantity} stock={product.stock} />
              </td>
              <td>{(quantity * product.price).toLocaleString("ko-KR")}</td>
              <td>
                <img
                  src={remove}
                  alt="remove icon"
                  className="cart_remove_icon"
                />
              </td>
            </tr>
          ))}
        </tbody>

 

 

 

이제 아래의 총 금액을 계산하면된다.

 

useState로 배송비를 제외한 합계를 관리한다. 


const CartPage = ({ cart }) => {
  const [subTotal, setSubTotal] = useState(0); //배송비 제외 합계

  //카트 수정될 때마다 합계 계산하기
  useEffect(() => {
    let total = 0;
    cart.forEach((item) => {
      total += item.product.price * item.quantity;
    });
    setSubTotal(total);
  }, [cart]);

 

그리고 cart가 바뀔 때마다 total 금액을 계산해서 저장함

 

 

저장된 금액을 원화로 변환하고, 결제 금액의 경우 배송비를 더해서 산정하면된다.

          <tr>
            <td>총 금액</td>
            <td>{subTotal.toLocaleString("ko-KR")}</td>
          </tr>
          <tr>
            <td>배송비</td>
            <td>3,000 원</td>
          </tr>
          <tr className="cart_bill_final">
            <td>결제금액</td>
            <td>{(subTotal + 3000).toLocaleString("ko-KR")}</td>
          </tr>
        </tbody>