Jieunny์ ๋ธ๋ก๊ทธ
S3) Unit 4. [์ค์ต] CMarket Hooks ๋ณธ๋ฌธ
๐ฃ ์ฅ๋ฐ๊ตฌ๋ ๊ตฌํํ๊ธฐ
โ๏ธ ์ฅ๋ฐ๊ตฌ๋์ ์ถ๊ฐ ๋ฐ ์ํ ๊ฐ์ ์ ๋ฐ์ดํธ
1. ๋ฉ์ธ ํ๋ฉด์์ '์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ' ๋ฒํผ์ ๋๋ฅธ ํ, ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง๋ก ์ด๋ํ๋ฉด ์ํ์ด ๋ด๊ฒจ์์ด์ผ ํ๋ค.
โก๏ธ ItemListContainer.js
import React from 'react';
import Item from '../components/Item';
function ItemListContainer({ items, cartItems, setCartItems }) {
const handleClick = (e, id) => {
let addItem = {
itemId: id,
quantity: 1,
}
for(let i=0; i<cartItems.length; i++){
if(id === cartItems[i].itemId) cartItems[i].quantity++; // ์ด๋ฏธ ์ฅ๋ฐ๊ตฌ๋์ ์์ผ๋ฉด ๊ฐ์ ์ฆ๊ฐ
else setCartItems([...cartItems, addItem]); // ์์ผ๋ฉด ๊ทธ ์์ดํ
์์ฒด๋ฅผ ๋ด์์ฃผ๊ธฐ
}
}
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} />)}
</div>
</div>
);
}
export default ItemListContainer;
โฐ App.js์์ items, cartItems, setCartItems state๋ฅผ props๋ก ๋ฐ์์จ๋ค.
โฐ ๋ฐ์์จ id์ ์๋์ ์์ฑ์ผ๋ก ๊ฐ์ง๋ ์ฅ๋ฐ๊ตฌ๋์ ์ถ๊ฐ ํ ์ ๊ฐ์ฒด๋ฅผ ์ ์ธํ๋ค.
โฐ cartItems ์ ์ฅ๋ฐ๊ตฌ๋ ์์ดํ ๋ชฉ๋ก์ ์๋ฏธํ๋ฉฐ, ์ด ๋ฐฐ์ด์ for๋ฌธ์ผ๋ก ๋๋ฉด์ ํ์ธํ๋ค.
โฐ ๋ง์ฝ id๊ฐ ์ฅ๋ฐ๊ตฌ๋์ ์๋ ์์ดํ id์ ๊ฐ๋ค๋ฉด ์ด๋ฏธ ์ฅ๋ฐ๊ตฌ๋์ ์๋ ์์ดํ ์ด๋ฏ๋ก ์๋ก ์ถ๊ฐํ์ง ์๊ณ ์๋๋ง ์ฆ๊ฐ์์ผ์ค๋ค.
โฐ id๊ฐ ์๋ค๋ฉด, ๊ทธ ์์ดํ ์ ์ฅ๋ฐ๊ตฌ๋์ ์๋ ๊ฒ์ด๋ฏ๋ก ์๊น ์ ์ธํ ์ ๊ฐ์ฒด์ ์๋ ์ฅ๋ฐ๊ตฌ๋์ ๋ด๊ธด ์์ดํ ์ ์ ๋ฐฐ์ด๋ก ๋ง๋ค์ด์ cartItems๋ฅผ ๊ฐฑ์ ํด์ค๋ค.
2. ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง์์ ๊ฐ ์์ดํ ์ ๊ฐ์๋ฅผ ๋ณ๊ฒฝํ ์ ์์ด์ผ ํ๋ค.
โก๏ธ ShoppingCart.js
import React, { useState } from 'react'
import CartItem from '../components/CartItem'
import OrderSummary from '../components/OrderSummary'
export default function ShoppingCart({ items, cartItems, setCartItems }) {
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) => {
let newCartItems = [...cartItems];
for(let i=0; i<newCartItems.length; i++){
if(newCartItems[i].itemId === itemId){
newCartItems[i].quantity = quantity;
//console.log(quantity);
setCartItems(newCartItems);
}
}
}
const handleDelete = (itemId) => {
setCheckedItems(checkedItems.filter((el) => el !== itemId));
setCartItems(cartItems.filter((el) => el.itemId !== 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
}
const renderItems = items.filter((el) => cartItems.map((el) => el.itemId).indexOf(el.id) > -1)
const total = getTotal()
return (
<div id="item-list-container">
<div id="item-list-body">
<div id="item-list-title">์ฅ๋ฐ๊ตฌ๋</div>
<span id="shopping-cart-select-all">
<input
type="checkbox"
checked={
checkedItems.length === cartItems.length ? true : false
}
onChange={(e) => handleAllCheck(e.target.checked)} >
</input>
<label >์ ์ฒด์ ํ</label>
</span>
<div id="shopping-cart-container">
{!cartItems.length ? (
<div id="item-list-text">
์ฅ๋ฐ๊ตฌ๋์ ์์ดํ
์ด ์์ต๋๋ค.
</div>
) : (
<div id="cart-item-list">
{renderItems.map((item, idx) => {
const quantity = cartItems.filter(el => el.itemId === item.id)[0].quantity
return <CartItem
key={idx}
handleCheckChange={handleCheckChange}
handleQuantityChange={handleQuantityChange}
handleDelete={handleDelete}
item={item}
checkedItems={checkedItems}
quantity={quantity}
/>
})}
</div>
)}
<OrderSummary total={total.price} totalQty={total.quantity} />
</div>
</div >
</div>
)
}
โฐ ์๋ ๋ณ๊ฒฝ์ handleQuantityChange ํจ์์์ ๊ตฌํํ๋ค.
โฐ state๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด์ cartItems๋ฅผ ๊น์ ๋ณต์ฌ๋ก ๊ฐ์ ธ์จ๋ค.
โฐ ๋ณต์ฌํ ๋ฐฐ์ด์ ๋๋ฉด์, ํด๋ฆญํ id์ ๊ฐ์ id์ ์์ดํ ์ ๋ง๋๋ฉด ๊ทธ ์์ดํ ์ quantity๋ฅผ ++ ํด์ค๋ค.
โฐ cartItems๋ฅผ ๋ณต์ฌํ ์ ๋ฐฐ์ด๋ก ๊ฐฑ์ ํด์ค๋ค.
3. ๋ด๋น๊ฒ์ด์ ๋ฐ์ ์ํ ๊ฐ์๊ฐ ์ฆ์ ํ์๋์ด์ผ ํ๋ค.
โก๏ธ Nav.js
import React from 'react';
import { Link } from 'react-router-dom';
function Nav({cartItems}) {
return (
<div id="nav-body">
<span id="title">
<img id="logo" src="../logo.png" alt="logo" />
<span id="name">CMarket</span>
</span>
<div id="menu">
<Link to="/">์ํ๋ฆฌ์คํธ</Link>
<Link to="/shoppingcart">
์ฅ๋ฐ๊ตฌ๋<span id="nav-item-counter">{cartItems.length}</span>
</Link>
</div>
</div>
);
}
export default Nav;
โฐ props๋ก ๋ฐ์์จ cartItems์ ๊ธธ์ด๋ฅผ ์ถ๋ ฅํด์ค๋ค.
โ๏ธ ์ฅ๋ฐ๊ตฌ๋๋ก๋ถํฐ ์ ๊ฑฐ
1. ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง์์ '์ญ์ ' ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋น ์ํ์ด ๋ชฉ๋ก์์ ์ญ์ ๋์ด์ผ ํ๋ค.
โก๏ธ ShoppingCart.js
import React, { useState } from 'react'
import CartItem from '../components/CartItem'
import OrderSummary from '../components/OrderSummary'
export default function ShoppingCart({ items, cartItems, setCartItems }) {
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) => {
let newCartItems = [...cartItems];
for(let i=0; i<newCartItems.length; i++){
if(newCartItems[i].itemId === itemId){
newCartItems[i].quantity = quantity;
//console.log(quantity);
setCartItems(newCartItems);
}
}
}
const handleDelete = (itemId) => {
setCheckedItems(checkedItems.filter((el) => el !== itemId));
setCartItems(cartItems.filter((el) => el.itemId !== 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
}
const renderItems = items.filter((el) => cartItems.map((el) => el.itemId).indexOf(el.id) > -1)
const total = getTotal()
return (
<div id="item-list-container">
<div id="item-list-body">
<div id="item-list-title">์ฅ๋ฐ๊ตฌ๋</div>
<span id="shopping-cart-select-all">
<input
type="checkbox"
checked={
checkedItems.length === cartItems.length ? true : false
}
onChange={(e) => handleAllCheck(e.target.checked)} >
</input>
<label >์ ์ฒด์ ํ</label>
</span>
<div id="shopping-cart-container">
{!cartItems.length ? (
<div id="item-list-text">
์ฅ๋ฐ๊ตฌ๋์ ์์ดํ
์ด ์์ต๋๋ค.
</div>
) : (
<div id="cart-item-list">
{renderItems.map((item, idx) => {
const quantity = cartItems.filter(el => el.itemId === item.id)[0].quantity
return <CartItem
key={idx}
handleCheckChange={handleCheckChange}
handleQuantityChange={handleQuantityChange}
handleDelete={handleDelete}
item={item}
checkedItems={checkedItems}
quantity={quantity}
/>
})}
</div>
)}
<OrderSummary total={total.price} totalQty={total.quantity} />
</div>
</div >
</div>
)
}
โฐ ์์ดํ ์ญ์ ๋ handleDelete ํจ์์์ ๊ตฌํํ๋ค.
โฐ cartItems์ filter๋ฅผ ์คํํด์, ํด๋ฆญํ id์ id๊ฐ ๊ฐ์ ์์ดํ ์ ์ ์ธํด์ค๋ค.
2. ๋ด๋น๊ฒ์ด์ ๋ฐ์ ์ํ ๊ฐ์๊ฐ ์ฆ์ ํ์๋์ด์ผ ํ๋ค.
โฐ ์์ 3๋ฒ๊ณผ ๊ฐ๋ค.
๐ฃ ์์ฐ ํ๋ฉด
'CodeStates > Training' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
S3) Unit 7. [์ค์ต] Cookie๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ (0) | 2023.03.07 |
---|---|
S3) Unit 4. [์ค์ต] CMarket Redux (0) | 2023.02.27 |
S3) Unit 3. [์ค์ต] Styled Component ๋ก UI ๊ตฌํํ๊ธฐ (0) | 2023.02.21 |
S3) Unit 2. [์ค์ต] Figma ํด๋ก (์ธ์คํ๊ทธ๋จ) (0) | 2023.02.17 |
S3) Unit 2. [์ค์ต] Figma (0) | 2023.02.16 |