일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 환경설정
- 정수형타입
- 어윈 사용법
- 한국건설관리시스템
- 집합_SET
- 예외처리
- 대덕인재개발원
- Java
- NestedFor
- oracle
- 예외미루기
- 인터페이스
- 다형성
- 객체 비교
- 추상메서드
- 컬렉션프레임워크
- 오라클
- abstract
- cursor문
- GRANT VIEW
- 컬렉션 타입
- 제네릭
- 생성자오버로드
- 사용자예외클래스생성
- exception
- 자동차수리시스템
- 메소드오버로딩
- 참조형변수
- EnhancedFor
- 자바
- Today
- Total
거니의 velog
(48) 리액트 장바구니 구성 3 본문
4. 상품 조회에서 장바구니 추가
* 장바구니에 존재하는 장바구니 아이템을 변경하거나 삭제하는 작업이 완료되었다면 이제 상품 조회 화면에서 장바구니에 상품을 추가하는 기능을 구현한다. 상품을 추가하면 장바구니 아이템을 생성하게 되는데 이때 서버에 전달하는 데이터는 '이메일, 상품번호, 수량'이다. 아래와 같은 상품 조회 화면에는 장바구니에 담기 버튼을 추가해 주어야 한다.
(1) 상품 조회 기능 수정
* 장바구니에 상품 추가 기능은 components/products/ReadComponent.js를 수정해야만 한다.
import React, { useEffect, useState } from "react";
import { getOne } from "../../api/productsApi";
import { API_SERVER_HOST } from "../../api/todoApi";
import useCustomMove from "../../hooks/useCustomMove";
import FetchingModal from "../common/FetchingModal";
import useCustomCart from "../../hooks/useCustomCart";
import useCustomLogin from "../../hooks/useCustomLogin";
const initState = {
pno: 0,
pname: "",
pdesc: "",
price: 0,
uploadFileNames: [],
};
const host = API_SERVER_HOST;
const ReadComponent = ({ pno }) => {
const [product, setProduct] = useState(initState);
//화면 이동용 함수
const { moveToList, moveToModify } = useCustomMove();
//fetching
const [fetching, setFetching] = useState(false);
//장바구니 기능
const { changeCart, cartItems } = useCustomCart();
//로그인 정보
const { loginState } = useCustomLogin();
const handleClickAddCart = () => {
let qty = 1;
const addedItem = cartItems.filter((item) => item.pno === parseInt(pno))[0];
if (addedItem) {
if (
window.confirm("이미 추가된 상품입니다. 추가하시겠습니까? ") === false
) {
return;
}
qty = addedItem.qty + 1;
}
changeCart({ email: loginState.email, pno: pno, qty: qty });
};
useEffect(() => {
setFetching(true);
getOne(pno).then((data) => {
setProduct(data);
setFetching(false);
});
}, [pno]);
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
(...)
<div className="flex justify-end p-4">
<button
type="button"
className="inline-block rounded p-4 m-2 text-xl w-32 text-white bg-green-500"
onClick={handleClickAddCart}
>
Add Cart
</button>
<button
type="button"
className="inline-block rounded p-4 m-2 text-xl w-32 text-white bg-red-500"
onClick={() => moveToModify(pno)}
>
Modify
</button>
<button
type="button"
className="rounded p-4 m-2 text-xl w-32 text-white bg-blue-500"
onClick={moveToList}
>
List
</button>
</div>
</div>
);
};
export default ReadComponent;
* Add Cart 버튼의 이벤트 처리는 handelClickAddCart() 를 통해서 처리하고 내부에서는 추가된 적이 있는 상품인지 검사해서 경고창을 보여준다. 장바구니에 추가된 적이 없는 상품은 경고창 없이 장바구니에 바로 추가된다.
[고려해야 하는 점들]
* 장바구니의 모든 정보는 데이터베이스를 이용해서 보관되기 때문에 애플리케이션 내의 상태 데이터라고 인식하기보다는 컴포넌트 간의 공유 데이터라고 보는 것이 더 적합한 설명이 될 수 있다. 실제 장바구니 구현의 고민은 조금 다른 곳에 있는데, 상품 정보가 수정되거나 삭제되는 경우이다. 삭제의 경우 FK로 작성되기 때문에 서버에서 문제가 발생할 수 있지만, 상품의 이름이나 가격을 수정하는 경우는 조금 사정이 다르다.
* 예를 들어, '상품의 가격이 수정되었다면 현재 상품을 장바구니에 담은 모든 사용자는 장바구니 내에 존재하는 상품 가격이 실시간으로 변동되어야 할까?' 는 상당히 중요한 문제이다. 이에 대한 가장 완벽한 해결책은 상품 자체가 불변 데이터인 경우가 되겠지만, 이는 변경되지 않는 것을 상정하기 때문에 논외의 상황이 된다.
* 이에 대한 절충안은 약간의 시간(5분/10분)을 두고 자동으로 갱신되도록 하는 것이다. 최근 개발에서는 다양한 라이브러리를 이용해서 일정 시간 동안만 리액트에서 데이터를 캐싱하는 기능들을 구현할 수 있을 것이다.
* 만일 최대한 실시간에 가깝게 데이터를 처리해야 한다면 Firebase를 이용하는 것이 가장 현실적인 해결책이 될 것이다.
'SpringBoot_React 풀스택 프로젝트' 카테고리의 다른 글
(50) 리액트 쿼리와 리코일 2 (0) | 2024.03.11 |
---|---|
(49) 리액트 쿼리와 리코일 1 (0) | 2024.03.11 |
(47) 리액트 장바구니 구성 2 (0) | 2024.03.08 |
(46) 리액트 장바구니 구성 1 (0) | 2024.03.08 |
(45) 장바구니 API 만들기 3 _ 수정 (0) | 2024.03.08 |