지영이의 개발 블로그
[React]리덕스를 적용해서 장바구니 기능 만들기! 본문
하나의 장바구니 상태를 여러 컴포넌트에 걸쳐 연동시키고 싶으나 계속되는 상태 및 함수의 props 전달로 인해 복잡해지는 문제가 발생한다.이때 리덕스를 도입하면 위 문제를 깔끔히 해결할 수 있다.
1.리덕스를 사용해서 장바구니 보여주기
<detail.js>
<button
onClick={() => {
dispatch(
addItem({
id: props.items[id].id,
name: props.items[id].title,
price: props.items[id].price,
count: 1,
})
)
: dispatch(addCount(props.items[id].id));
주문하기
</button>
<store.js>
import { configureStore, createSlice } from "@reduxjs/toolkit";
let cart = createSlice({
name: "cart",
initialState: [
{ id: 11, name: "White and Black", price: 1000, count: 1 },
{ id: 12, name: "Grey Yordan", price: 4000, count: 1 },
{ id: 13, name: "oh my god", price: 2000, count: 1 },
],
reducers: {
addItem(state, action) {
state.push(action.payload);
},
});
export let {addItem } = cart.actions;
export default configureStore({
reducer: {
cart: cart.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
<cart.js>
import { Table } from "react-bootstrap";
import { useSelector, useDispatch } from "react-redux";
function Cart() {
let state = useSelector((state) => {
return state;
});
let dispatch = useDispatch();
return (
<Box>
<Table striped>
<thead>
<tr>
<th>상품번호</th>
<th>상품정보</th>
<th>판매가</th>
<th>수량</th>
<th>갯수</th>
</tr>
</thead>
<tbody>
{state.cart.map((a, i) => (
<tr key={i}>
<td>{state.cart[i].id}</td>
<td>{state.cart[i].name}</td>
<td>{state.cart[i].price * state.cart[i].count}</td>
</tr>
))}
</tbody>
</Table>
</Box>
);
}
export default Cart;
2.장바구니 수량 증가 버튼 만들기 + 상품이 중복되는 문제 해결하기
🤷♀️여기서 문제가 생기는데 장바구니에 추가하기 버튼을 누르면 장바구니에 상품이 추가 되는데
중복되는 상품이 계속해서 추가 되는것을 볼수있음🤷♀️
이를 해결 하기 위해 findindex 함수를 사용해주었는데 중복된 id가 있으면 그 해당 디테일 아이디 숫자가 남고, 중복된 id가 없으면 -1이 남습니다
그 dupValue값이 -1 와 같은지 비교해 일치하면 새 항목을 추가해주고, 그렇지 않으면 해당 id값에 수량 증가해주었습니다.
<detail.js>
let state = useSelector((state) => {
return state.cart;
});
<button
onClick={() => {
let dupValue = state.findIndex((a) => {
return a.id === items[id].id;
});
dupValue === -1
? dispatch(
addItem({
id: items[id].id,
name: items[id].title,
price: items[id].price,
count: 1,
})
)
: dispatch(addCount(items[id].id));
>
주문하기
</button>
store.js 안에 state 수정해주는 함수를 만들고
원할 때 import 해서 사용합니다. 근데 dispatch() 로 감싸서 써야함 (useDispatch)
store.js
import {
configureStore,
createSlice,
getDefaultMiddleware,
} from "@reduxjs/toolkit";
let cart = createSlice({
name: "cart",
initialState: [
{ id: 11, name: "White and Black", price: 1000, count: 1 },
{ id: 12, name: "Grey Yordan", price: 4000, count: 1 },
{ id: 13, name: "oh my god", price: 2000, count: 1 },
],
reducers: {
addCount(state, action) {
let 번호 = state.findIndex((a) => {
return a.id === action.payload;
});
state[번호].count++;
// state[action.payload].count++
},
addItem(state, action) {
state.push(action.payload);
},
},
});
export let { addCount, addItem } = cart.actions;
export default configureStore({
reducer: {
cart: cart.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
여기서 state[action.payload].count++ 으로 해줘도 되지만 정확한 기능을 위해서 (예를들면 정렬을 쓴다거나 할때를 방지해서) 조건을걸어줍니다
let 번호 = state.findIndex((a) => {
return a.id === action.payload;
});
3.상품금액과 총금액 계산하기
갯수 버튼을 누를때마다 판매가가 증가하고 판매가를 모두 더한값을 총금액으로 표시해 줘 보도록 하겠습니다
<cart.js>
let total = state.cart.reduce(
(accu, cart) => accu + cart.price * cart.count,
0
);
array.reduce()
reduce()메서드는 배열의 각 요소에 대해 주어진 reducer 함수를 실행하고, 하나의 결과값을 반환한다. 배열 축소의 원리로 작용한다. 즉 여러개의 값이 담긴 배열이 줄어서 최종적으로 하나의 값으로 만드는 과정
arr.reduce(callback (누산기, 현재값 [, currentindex [, array]]){
//return 누적 결과의 결과 값
[, 초기값]}
reduce 함수를 사용해서 배열의 각 요소를 순회하며 callback함수의 실행 값을 누적하여 하나의 결과값을 반환하면 됨! 초기값은 합을 구하므로 0에서 부터 시작합니다.
4.삭제버튼 만들기
redux에서 state를 업데이트 하는 함수를 만들고 실행시켜줌으로써 간단하게 해결 할 수 있었다
store.js
import {
configureStore,
createSlice,
} from "@reduxjs/toolkit";
let cart = createSlice({
name: "cart",
initialState: [
{ id: 11, name: "White and Black", price: 1000, count: 1 },
{ id: 12, name: "Grey Yordan", price: 4000, count: 1 },
{ id: 13, name: "oh my god", price: 2000, count: 1 },
],
reducers: {
deltetItem(state, action) {
let copy = [...state];
let 필터 = copy.filter((a) => a.id !== action.payload);
return 필터;
},
},
});
export let { deltetItem } = cart.actions;
cart.js
<tbody>
{state.cart.map((a, i) => (
<tr key={i}>
<td>{state.cart[i].id}</td>
<td>{state.cart[i].name}</td>
<td>{state.cart[i].price * state.cart[i].count}</td>
<td>{state.cart[i].count}</td>
<td>
<button
onClick={() => {
dispatch(addCount(state.cart[i].id));
// let total =(`${state.cart[i].price * state.cart[i].count}`)
}}
>
+
</button>
</td>
<td>
<button
onClick={() => {
dispatch(deltetItem(state.cart[i].id));
}}
>
X
</button>
</td>
</tr>
))}
총금액 : {total}
</tbody>
'React > 쇼핑몰 만들기' 카테고리의 다른 글
[React로 만든 쇼핑몰]localstorage로 최근 본 상품 기능 만들기!! (0) | 2022.07.10 |
---|---|
[React로 만든 쇼핑몰]오류 해결하기 (0) | 2022.07.10 |
[React로 만든 쇼핑몰]detail페이지(useNavigate() & useLocation() ) (0) | 2022.06.27 |
쇼핑몰 프로젝트 - 상품목록 더보기 버튼 (0) | 2022.06.16 |
쇼핑몰 프로젝트 -Navbar,Carousel(슬라이드 배너),sweetalert (0) | 2022.06.14 |
Comments