๋ฏธ์์ฑ์ Cmarket์ ๊ตฌ์ฑํ๋ React์ฝ๋๊ฐ ์๋ค. ์ด ์ฝ๋๋ฅผ ๋ง์ ์์ฑํด์ ์์ฑ๋ market์ ๊ตฌํํ๋ ๊ฒ์ด ๋ชฉํ๋ค.
<ํ์ด์ง ๊ด๋ จ ์ปดํฌ๋ํธ>
App.js
: Cmarket์์ ์ต์์ ์ปดํฌ๋ํธ ์ด ์์์ Items
์ carItems
์ ์ํ๊ฐ ๋ค์ด์๋ค.ItemListContainer.js
: App.js
์ ์์ ์ปดํฌ๋ํธ๋ก ์ํ ๋ฆฌ์คํธ ํ์ด์ง๋ฅผ ๋ํ๋ด๋ ์ปดํฌ๋ํธShoppingCart.js
: App.js
์ ์์ ์ปดํฌ๋ํธ๋ก ์ฐ ๋ชฉ๋ก ๋ฆฌ์คํธ ํ์ด์ง๋ฅผ ๋ํ๋ด๋ ์ปดํฌ๋ํธ<ํ์ด์ง ๋ด๋ถ ์ปดํฌ๋ํธ>
Nav.js
: App.js
์ ์์ ์ปดํฌ๋ํธ๋ก ๊ฐ ํ์ด์ง ์ ๋ค๋น๊ฒ์ด์
์ ๋ํ๋ด๋ ์ปดํฌ๋ํธCartItem.js
: ShoppingCart.js
์ ์์ ์ปดํฌ๋ํธ๋ก ์ํ์ ๋ํ๋ด๋ ์ปดํฌ๋ํธItem.js
: ItemListContainer.js
์ ์์ ์ปดํฌ๋ํธ๋ก ์ํ์ ๋ํ๋ด๋ ์ปดํฌ๋ํธOrderSummary.js
: ShoppingCart.js
์ ์์ ์ปดํฌ๋ํธ๋ก ์ํ์ ์ข
ํฉ์ ์ผ๋ก ํ์ํด์ฃผ๋ ์ปดํฌ๋ํธstate.js
: ์ํ๋ค์ดitems
์ cartItems
๋ก ๋ฐฐ์ด์ ํํ๋ก ๊ฐ์ฒด ์์ ๋ด๊ฒจ์๋ ์ผ์ข
์ DB// state.js
export const initialState =
{
"items": [
{
"id": 1,
"name": "๋
ธ๋ฅธ์ ๋ถ๋ฆฌ๊ธฐ",
"img": "../images/egg.png",
"price": 9900
},
{
"id": 2,
"name": "2020๋
๋ฌ๋ ฅ",
"img": "../images/2020.jpg",
"price": 12000
},
{
"id": 3,
"name": "๊ฐ๊ตฌ๋ฆฌ ์๋",
"img": "../images/frog.jpg",
"price": 2900
},
{
"id": 4,
"name": "๋ฏ์ด์จ ๋ณด๋๋ธ๋ญ",
"img": "../images/block.jpg",
"price": 4900
},
{
"id": 5,
"name": "์นผ๋ผ ๋ฆฝ์คํฑ",
"img": "../images/lip.jpg",
"price": 2900
},
{
"id": 6,
"name": "์์ด ์์ฆ",
"img": "../images/fish.jpg",
"price": 3900
},
{
"id": 7,
"name": "์ฐ์ปด ๋งคํธ",
"img": "../images/welcome.jpg",
"price": 6900
},
{
"id": 8,
"name": "๊ฐ์ ๋ชจ์",
"img": "../images/hat.jpg",
"price": 9900
}
],
"cartItems": [
{
"itemId": 1,
"quantity": 1
},
{
"itemId": 5,
"quantity": 7
},
{
"itemId": 2,
"quantity": 3
}
]
}
์ฐ๋ฆฌ๋ ์ง๊ธ ๊น์ง ์๋ฒ๋ฅผ ํตํ ๋ผ์ฐํ ์ ๋ฐฐ์ ๋ค. ์ง๊ธ ์ด ํ์ด์ง์์๋ ์๋ฒ๋ฅผ ํตํ์ง ์๊ณ ํด๋ผ์ด์ธํธ์์ ๋ผ์ฐํ ์ ์ค์ํ๋ ค๊ณ ํ๋ค. ๊ทธ ์ ์ ๋ค์ ํ๋ฒ ๋ผ์ฐํ ์ด ๋ฌด์์ธ๊ฐ? ๋ฅผ ์ง๊ณ ๋์ด๊ฐ์.
๋ผ์ฐํ : URL ์กฐ๊ฑด์ ๋ฐ๋ฅธ ๋ถ๊ธฐ๋ฅผ ๋๋๋ ๊ฒ
์๋ฒ๋ฅผ ํตํด์ ๋ผ์ฐํ ์ ๋๋๋ ๊ฒ์ ์ด์ ์ ์์๋ณด์๋ค. ๊ทธ๋ ๋ค๋ฉด Client Side Routing๋ ์ด๋ป๊ฒ ๊ตฌํํ ๊น? ์๋ ์ฝ๋๋ฅผ ํตํด ์ดํด๋ณด์.
return (
<Router>
<Nav />
<Switch>
<Route exact={true} path="/">
<ItemListContainer items={items} />
</Route>
<Route path="/shoppingcart">
<ShoppingCart cartItems={cartItems} items={items} />
</Route>
</Switch>
</Router>
);
์ ์ฝ๋๋ App.js
๋ด์์ ์ต์ข
์ ์ผ๋ก ํ๋ฉด์ ์ถ๋ ฅํ๋ ๋ฆฌํด ๊ฐ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด๋ค. ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด Router
, Switch
, Route
๋ก ๊ตฌ๋ถ์ ์ง์ด์ค๋๋ค.
๋ผ์ฐํฐ๊ฐ
/
๋ฉด ItemListContainer ์ปดํฌ๋ํธ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ/shoppingcart
๋ฉด Soppingcart ์ปดํฌ๋ํธ๋ฅผ ์ถ๋ ฅํด์ค๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด ๊ฒฝ๋ก๋ ์ด๋ป๊ฒ ํด์ ๋๋ ํ์ํ ์ ์๋๊ฐ ๊ทธ๊ฑด Nav.js
๋ฅผ ์ดํด๋ณด๋ฉด ๋๋ค.
function Nav() {
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">0</span>
</Link>
</div>
</div>
);
}
์ ์ฝ๋์์ Link
์ปดํฌ๋ํธ์ to
์์ฑ์ ํตํด์ ํด๋ฆญ์ ๋ผ์ฐํฐ๊ฐ ๋ณ๊ฒฝ๋๋๋ก ์ฑ์ ํ ์ ์๋ค.
๋จผ์ ํ์ํ ๊ฒ์ App.js
์ ์ํ๋ฆฌ์คํธ์ state์ ์นดํธ๋ฆฌ์คํธ์ state๋ฅผ ์์ฑํ๊ณ ๊ทธ state๋ฅผ ๋ค๋ฃฐ ์ ์๋ ํจ์๋ฅผ Hook์ ํตํด์ ์์ฑํ๋ค.
// App.js
// initialState๋ import๋ฅผ ํตํด์ state์ ์๋ ๊ฐ์ ๋ฐ์์จ ๊ฒ์ด๋ค.
function App() {
const [items, setItems] = useState(initialState.items);
const [cartItems, setCartItems] = useState(initialState.cartItems);
return (
...
}
์ด ํ Item
์์ ์๋ ์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฅ๋ฐ๊ตฌ์น์ ์ํ์ด ์ถ๊ฐ๋๊ณ Nav
์ปดํฌ๋ํธ์ ์ํ์ ๊ฐฏ์๊ฐ ์
๋ฐ์ดํธ ๋๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
// App.js
function App() {
const [items, setItems] = useState(initialState.items);
const [cartItems, setCartItems] = useState(initialState.cartItems);
const addToCart = (itemId) => {
const found = cartItems.filter((el) => el.itemId === itemId)[0]
// ์ธ์๋ก ๋ฐ์ itemId์ ์ํ์ด ์ด๋ฏธ cartItems์ ์์ผ๋ฉด ๊ทธ ์ํ์ found์ ํ ๋นํด์ค๋ค.
if(found) { // found๊ฐ ์์ผ๋ฉด ์ฆ, ์ด๋ฏธ ์นดํธ๋ชฉ๋ก์ ์๋ ๊ฒ์ด๋ฉด
setQuantity(itemId, found.quantity + 1)
//์ํ๋ฆฌ์คํธ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์๋ ๊ทธ ์ํ์ quantitiy๊ฐ์ ์ฆ๊ฐ์ํจ๋ค.
}else{ // found๊ฐ ์์ผ๋ฉด ์ฆ, ์นดํธ๋ชฉ๋ก์ ์๋ ์ํ์ด๋ฉด
setCartItems([...cartItems, {itemId, quantity: 1}])
//์ํ ๋ชฉ๋ก์ ํด๋น ์ํ์ ์์ด๋์ ์๋์ ์ถ๊ฐํด์ค๋ค.
}
}
const setQuantity = (itemId, quantity) => { //ํด๋น ์์ดํ
์์ด๋์ ์๋์ ์
๋ ฅ ๋ฐ๋๋ค.
const found = cartItems.filter((el) => el.itemId === itemId)[0] //ํด๋น ์์ดํ
ํ ๋น
const idx = cartItems.indexOf(found) // ํด๋น ์์ดํ
์ ์์ฐจ ๊ฐ ํ ๋น
const cartItem = { //ํด๋น ์์ดํ
์ ์๋์ ๋ณ๊ฒฝํด์ ๋ค์ ์ ์ํ๋ค.
itemId,
quantity
}
setCartItems([...cartItems.slice(0, idx), cartItem, ...cartItems.slice(idx + 1)])
//ํด๋น ์์ดํ
์ ์์น์ ์๋์ ๋ณ๊ฒฝํด์ ๋ค์ ์ ์ํ ์์ดํ
์ ๋ผ์ ๋ฃ์ด์ ์ฌ ์ ์ํ๋ค.
}
return (
...
<Nav cartItems={cartItems}/>
...
<ItemListContainer items={items} handleAdd={addToCart} />
// addToCart ํจ์๋ฅผ ItemListContainer ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌํด์ค๋ค.
...
}
// ItemListContainer.js
function ItemListContainer({ items, handleAdd }) {
const handleClick = () => handleAdd(item.id)
// handleClick์ ์คํํ๋ฉด ํด๋น ์์ดํ
์ id ๊ฐ์ ๊ฐ์ง๊ณ handleAddํจ์๋ฅผ ์คํํ๋ค.
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>
);
}
// Item.js
function Item({ item, handleClick }) {
return (
<div key={item.id} className="item">
<img className="item-img" src={item.img} alt={item.name}></img>
<span className="item-name">{item.name}</span>
<span className="item-price">{item.price}</span>
<button className="item-button" onClick={(e) => handleClick(e, item.id)}>์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ</button>
</div>
)
}
์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์์ดํ
๋ฆฌ์คํธ์ ์๋ ์ํ์ ์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ๋ฅผ ํด๋ฆญํ๋ฉด cartItems
๋ฐฐ์ด์ ํด๋น ์์ดํ
์ด ๋ด๊ธฐ๊ณ ์ด๋ฏธ ํด๋น ์์ดํ
์ด ์๋ค๋ฉด ์๋์ ๋๋ฆด ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ Nav
์ปดํฌ๋ํธ์ ํ์๋๋ ์ํ์ ๊ฐฏ์ ๋ํ ๋ณ๊ฒฝ๋์ด์ผ ํ ๊ฒ์ด๋ค.
// Nav.js
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>
);
}
์ฅ๋ฐ๊ตฌ๋ ์์ ํ์๋๋ ์ํ์ ๊ฐฏ์๋ cartItems
๋ฐฐ์ด์ ๊ฐ์ฒด์ ํํ๋ก ๋ด๊ฒจ ์๋ค. ๋ค์ ๋งํด์ cartItems
์ ๊ธธ์ด๊ฐ ๊ฒฐ๊ตญ ๋ด๊ฒจ์๋ ์ํ์ ๊ฐฏ์๊ฐ ๋๋ค๋ ๋ง์ด๋ค. ๋๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด์ฃผ๋ฉด ๋๋ค.
์ฅ๋ฐ๊ตฌ๋๋ก ๋ถํฐ ์ํ์ ์ ๊ฑฐํ๋ ค๋ฉด CartItem
์ ์๋ ์ญ์ ๋ฒํผ ์ ํด๋ฆญํ์ ๋ cartItems
์ ๋ฐฐ์ด์์ ํด๋น ์ํ์ด ์ฌ๋ผ์ง๊ฒ ํ๋ฉด ๋๋ค. ์ด๋ฅผ ๊ตฌํํ๋ ๋ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด์
// App.js
function App() {
const [items, setItems] = useState(initialState.items);
const [cartItems, setCartItems] = useState(initialState.cartItems);
...
const removeFromCart = (itemId) => {
setCartItems(cartItems.filter((el) => el.itemId !== itemId))
// ์ธ์๋ก ๋ฐ์ itemId์ ์ผ์นํ์ง ์๋ ๊ฐ๋ค์ ํํฐ๋งํด์ cartItems๋ฅผ ๋ค์ ํ ๋นํ๋ค.
}
return (
...
<ShoppingCart cartItems={cartItems} items={items} handleDelete = {removeFromCart}/>
...
)
}
// ShoppingCart.js
function ShoppingCart({ items, cartItems, handleDelete: onDelete })