Lecture/์ฝ๋์คํ
์ด์ธ
[SEB FE] Section3 unit 4 (3) Cmarket Redux
Dong _ hwa
2023. 5. 18. 08:46

- ์์ดํ ๋ฆฌ์คํธ ํ์ด์ง(ItemListContainer)์ ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง(ShoppingCart) ์ด ๋ ํ์ด์ง๋ก ๊ฐ๋จํ๊ฒ ๊ตฌ์ฑ๋ฉ๋๋ค.
- Store์ initial state์๋ ์ ์ฒด ์์ดํ ๋ชฉ๋ก(items), ์ฅ๋ฐ๊ตฌ๋ ๋ชฉ๋ก(cartItems)์ด ๋ค์ด์์ต๋๋ค.
- ๊ฐ ItemListContainer, ShoppingCart ํ์ด์ง ์ปดํฌ๋ํธ ๋ฐ components ํด๋์ ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ค์์ Store(state)์ ์ ๊ทผํด ๋ณด์ธ์.(Redux์์ ์ ๊ณตํ๋ hooks, useDispatch, useSelector๋ฅผ ์ฌ์ฉํฉ๋๋ค.)
โ๏ธ Action
actions / index.js
export const addToCart = (itemId) => {
return {
type: ADD_TO_CART,
payload: {
quantity: 1,
itemId
}
}
}
export const removeFromCart = (itemId) => {
return {
type : REMOVE_FROM_CART,
payload: {
itemId
}
}
}
export const setQuantity = (itemId, quantity) => {
return {
type : SET_QUANTITY,
payload : {
itemId,
quantity
}
}
}
โ๏ธ Dispatch
pages / ItemListContainer.js
import React from 'react';
import { addToCart, notify } from '../actions/index';
import { useSelector, useDispatch } from 'react-redux';
import Item from '../components/Item';
function ItemListContainer() {
const state = useSelector(state => state.itemReducer);
const { items, cartItems } = state;
const dispatch = useDispatch();
const handleClick = (item) => {
if (!cartItems.map((el) => el.itemId).includes(item.id)) {
//TODO: dispatch ํจ์๋ฅผ ํธ์ถํ์ฌ ์์ดํ
์ถ๊ฐ์ ๋ํ ์ก์
์ ์ ๋ฌํ์ธ์.
dispatch(addToCart(item.id))
dispatch(notify(`์ฅ๋ฐ๊ตฌ๋์ ${item.name}์ด(๊ฐ) ์ถ๊ฐ๋์์ต๋๋ค.`))
}
else {
dispatch(notify('์ด๋ฏธ ์ถ๊ฐ๋ ์ํ์
๋๋ค.'))
}
}
return (
<div id="item-list-container">
<div id="item-list-body">
<div id="item-list-title">์ธ๋ชจ์๋ ์ ๋ฌผ ๋ชจ์</div>
{items.map((item, idx) => <Item item={item} key={idx} handleClick={() => {
handleClick(item)
}} />)}
</div>
</div>
);
}
export default ItemListContainer;
pages / ShoppingCart.js
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { removeFromCart, setQuantity } from '../actions';
import CartItem from '../components/CartItem'
import OrderSummary from '../components/OrderSummary'
export default function ShoppingCart() {
const state = useSelector(state => state.itemReducer);
const { cartItems, items } = state
const dispatch = useDispatch();
const [checkedItems, setCheckedItems] = useState(cartItems.map((el) => el.itemId))
const handleCheckChange = (checked, id) => {
if (checked) {
setCheckedItems([...checkedItems, id]);
}
else {
setCheckedItems(checkedItems.filter((el) => el !== id));
}
};
const handleAllCheck = (checked) => {
if (checked) {
setCheckedItems(cartItems.map((el) => el.itemId))
}
else {
setCheckedItems([]);
}
};
const handleQuantityChange = (quantity, itemId) => {
//TODO: dispatch ํจ์๋ฅผ ํธ์ถํ์ฌ ์ก์
์ ์ ๋ฌํ์ธ์.
dispatch(setQuantity(itemId, quantity))
}
const handleDelete = (itemId) => {
setCheckedItems(checkedItems.filter((el) => el !== itemId))
//TODO: dispatch ํจ์๋ฅผ ํธ์ถํ์ฌ ์ก์
์ ์ ๋ฌํ์ธ์.
dispatch(removeFromCart(itemId))
}
const getTotal = () => {
let cartIdArr = cartItems.map((el) => el.itemId)
let total = {
price: 0,
quantity: 0,
}
for (let i = 0; i < cartIdArr.length; i++) {
if (checkedItems.indexOf(cartIdArr[i]) > -1) {
let quantity = cartItems[i].quantity
let price = items.filter((el) => el.id === cartItems[i].itemId)[0].price
total.price = total.price + quantity * price
total.quantity = total.quantity + quantity
}
}
return total
}
โ๏ธ Reducer
reducers / itemReducer
import { REMOVE_FROM_CART, ADD_TO_CART, SET_QUANTITY } from "../actions/index";
import { initialState } from "./initialState";
const itemReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_CART:
return Object.assign({}, state, {
cartItems: [...state.cartItems, action.payload]
})
case REMOVE_FROM_CART:
let list = state.cartItems.filter(el => el.itemId !== action.payload.itemId)
return Object.assign({}, state, {
cartItems: list
})
case SET_QUANTITY:
let idx = state.cartItems.findIndex(el => el.itemId === action.payload.itemId)
let arr = state.cartItems.map ((el, index) => {
return idx === index ? action.payload : el
})
return Object.assign({}, state, {
cartItems: arr
})
default:
return state;
}
}
export default itemReducer;
์ด๋ ค์ ๋ ์ ๐งโ๏ธ
case SET_QUANTITY:
let idx = state.cartItems.findIndex(el => el.itemId === action.payload.itemId)
let arr = state.cartItems.map ((el, index) => {
return idx === index ? action.payload : el
})
return Object.assign({}, state, {
cartItems: arr
})
๋ด๊ฐ ์ด์ฐ์ ์ฐ ๊ตฌํํ ์ฝ๋
case SET_QUANTITY:
let idx = state.cartItems.findIndex(el => el.itemId === action.payload.itemId)
return Object.assign({}, state, {
cartItems: [...state.cartItems.slice(0, idx), action.payload,
...state.cartItems.slice(idx + 1)]
});
์ด๊ฒ ๋ ํผ๋ฐ์ค ์ฝ๋์ด๊ณ ,
return {
...state,
cartItems: [...state.cartItems.slice(0, idx), action.payload, ...state.cartItems.slice(idx + 1)]
}
์ธํฐ๋ท์๋ Object.assign ๋ ์ฌ์ฉํ์ง ์์ ์ฝ๋๊ฐ ์ ์ผ ๋ง์ด ๋ณด์ธ๋ค.
๋ด๊ฐ ์ด์ฐ์ ์ฐ ๊ตฌํํ ์ฝ๋๋ ๋์๋ณด์ด๋ ์ง๊ด์ ์ธ ์ฝ๋๋ผ์, ์ดํด๊ฐ ๋๋๋ฐ
๋๋ง ์ด ๋ ํผ๋ฐ์ค๋ค์ด ์ดํด๊ฐ ์๊ฐ๋ ๊ฑด์ง ใ
_ใ
๋จธ๋ฆฌ๊ฐ ์ ๋์๊ฐ๋ค...