일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- C++
- 프로그래머스
- Java
- js to ts
- 타입스크립트
- 정렬
- web
- CPU 스케줄링
- 분할메모리할당
- 자료구조
- 협업
- 공부
- 토이프로젝트
- memory
- 리덕스장바구니
- 알고리즘
- Redux
- Spring
- error
- 스프링
- codeup
- Operating System
- 백준
- react
- 코드업
- 일상
- 파이썬
- OS
- react-redux
- 기초100제
- Today
- Total
감자튀김 공장🍟
[React] 장바구니 수량 변경 문제2 본문
저번의 문제는 Quantity 값을 변경하면 console 값에는 반영이 되어서 출력이 되는데 화면이 리렌더링 되지 않는 점이였다. 몇 번의 시행착오를 겪으면서 생긴 문제점들을 나열해보자면
- 화면에 바뀐 값이 리렌더링이 안돼서 useState로 값을 관리할려고 추가했더니 렌더링 무한루프에 빠졌다.
- 최종 금액 값이 리렌더링이되면 장바구니 배열의 수량도 같이 렌더링이 되어야하는데 둘 중에 하나만 리렌더링 된다.
- id: 3의 quantity를 3에서 5로 변경하고 id: 10의 quantity를 변경하면 id 마다 quantity가 변경되는 것이 아니라 한 값에서 변경이 이루어졌다. 즉, id: 10의 quantity가 뭐였던 id: 3의 마지막 값인 5에서 변경이 이루어졌다.
- 수량 조절 버튼(+/-)을 두 번 누르면 TypeError: Cannot read property 'Id' of undefined 오류가 떴다.
- 객체 배열 Quantity 값이 변경되는 것이 아니라 배열에 Quantity가 새로 추가된다.
줄여보자면 이정도의 오류가 있었고, 원래는 더 대환장스러운 오류들도 있었다. 증감 버튼을 누르면 갑자기 화면에서 출력되어있던 내용들이 다 사라진다던가...
원래는 Cart.js에서 FinalCart.js로 장바구니 리스트를 넘겨주고 FianlCart.js에서 넘겨받은 리스트로 json 객체를 만들어서 화면에 리렌더링하고 그랬었는데, 굳이 그렇게 할 필요가 있나? 느꼈었다. useState로 변경되는 값들을 제어하기 위해서 애초에 Cart.js에서 json 객체를 만들어서 FinalCart.js로 넘겨주고 FinalCart.js에서는 받은 json 객체를 useState로 다루는 것으로 생각을 바꿔보았다.
왜냐하면 useState 없이 값이 바뀔 때 리렌더링이 되는 방법이 없다고 생각했기 때문이다.
Cart.js
import React from 'react';
import {Link} from 'react-router-dom';
import {useSelector} from 'react-redux';
function Cart() {
const cart = useSelector((store) => store.cartReducer);
const list = [];
const res = [];
const arr = Object.create(null);
let sum = 0;
const cartItem = cart.length >= 1 ? cart.map((item, idx) => {
sum += item.price;
return (
<div key={idx} item={item} idx={idx}>
<div>{item.name_kor}</div>
</div>
);
}) : <div>장바구니가 비어있습니다.</div>;
for(let i = 0; i < cart.length; i++) { //json 객체로 만들기
const json = Object.create(null);
json.Id = cart[i].id;
json.Name = cart[i].name_kor;
json.Price = cart[i].price;
list.push(json);
}
for(let i = 0; i < list.length; i++) { // 같은 id 객체 삭제 후, Quantity +1
if(!arr[list[i].Id]) {
res.push(list[i]);
}
arr[list[i].Id] = ((arr[list[i].Id] || 0) + 1);
}
for (let j = 0; j < res.length; j++) {
res[j].Quantity = arr[res[j].Id];
}
return (
<div>
<br />
<hr />
<h3>장바구니 화면입니다.</h3>
<div>
{cartItem}
</div>
<div className='cartStyle'>
<div>금 액 : {sum}</div><br />
<Link to= {{
pathname: '/finalcart',
state: {sum, res},
}}>
<div><button>결제하기</button></div>
</Link>
</div>
</div>
);
}
export default Cart;
이렇게 장바구니에 담기는 부분은 Redux로, 장바구니 수량 변경을 위해 리덕스로 만들어진 장바구니 리스트들을 json 객체로 변경하고, 중복 id 객체는 삭제 후 Qauntity 항목을 추가하면서 수량을 +1 씩 하는 구조로 바꾸었다. 결제하기 버튼을 누르면서 FinalCart.js로 결제할 금액인 sum과 주문 리스트 객체인 res를 넘겨주었다.
FinalCart.js
import React, {useEffect, useState} from 'react';
import {useLocation} from 'react-router-dom';
function FinalCart() {
const cart = useLocation();
const [finalSum, setfinalSum] = useState(cart.state.sum); //sum 값 초기화
const [finalRes, setfinalRes] = useState([]); //res를 받을 finalRes
useEffect(() => {
setfinalSum(finalSum);
setfinalRes(cart.state.res);
});
const onIncrease = (idx) => {
setfinalRes(finalRes[idx]['Quantity'] += 1);
totalSum(finalRes);
};
const onDecrease = (idx) => {
if(finalRes[idx].Quantity > 0) {
setfinalRes(
finalRes[idx]['Quantity'] -= 1,
);
} else {
setfinalRes(
finalRes[idx]['Quantity'] = 0,
);
}
totalSum(finalRes);
};
const totalSum = (cart) => {
let total = 0;
Object.keys(cart).map((item) => {
total += finalRes[item].Price * finalRes[item].Quantity;
});
setfinalSum(total);
};
const list = Object.keys(finalRes).map((item, idx) => {
return (
<div key={idx}>
<div>{finalRes[item].Name}</div>
<div>{finalRes[item].Price}</div>
<div>{finalRes[item].Quantity}</div>
<button onClick={() => onIncrease(idx)}>+</button>
<button onClick={() => onDecrease(idx)}>-</button>
<br /><br />
</div>
);
});
return (
<div>
<h3>최종 장바구니 화면입니다.</h3>
<div>총 금 액 : {finalSum}</div>
<br />
<hr />
<div>{list}</div>
</div>
);
}
export default FinalCart;
FinalCart.js에서는 uesState, uesEffect로 변경되는 값들을 관리, 리렌더링한다.
증감버튼에서는 해당 리스트의 인덱스 값을 보내 finalRes의 해당 인덱스의 Quantity 값을 변경하고, 그에 따른 가격도 변경하는 코드를 구현했다.
막상 보니까 그렇게 안어렵고 복잡하지않은데 저 부분을 해결하는데에 너무 오랜 시간이 들어서 조금 자괴감이 들었지만 해냈다는 것에 정말 만족한다^_^!!
+) Redux로 quantity를 변경하는 코드를 추가 구현했다
(전 블로그에서 2021.02.24 18:28에 작성된 글입니다.)
'Study > React' 카테고리의 다른 글
[React] Redux 장바구니 수량 변경1 (최종) (0) | 2021.03.29 |
---|---|
[React&antd] Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>. (0) | 2021.03.02 |
[React&JS] TypeError: Cannot convert object to primitive value (0) | 2021.03.02 |
[React] 장바구니 수량 변경 문제 (0) | 2021.03.02 |
[React] < button >으로 state 값을 자식 컴포넌트로 넘겨주기 (0) | 2021.03.02 |