카트를 누르면, Modal 이 나오는 화면을 구축하고 싶다.
프로세스를 생각해본다.
1. "카트" 를 만든다.
2. "카트 버튼"을 누르면, "카트" 가 "모달" 형태로 만들어져 렌더되게 만든다.
3. 그러므로 "카트 모달"은 "포털"을 이용하여, "index.html 에 연결한다."
4. "카트 모달이 실제로 렌더되는 곳은 index.html"이다.
5. "카트가 직접 실행되는 곳은, Header의 카트 버튼"이다.
6. "카트 버튼"에서 "카트 모달"을 렌더하면, "카트 모달"은 "최상위 포지션의 형제 컴포넌트로 렌더된다."
7. "실행되는 곳"에서는 State 를 통해, 끄고, 켜고를 만든다.
8. 또한, "끄고 켜는 함수" 를 "카트 모달"로 props 드릴리으로 넘겨 "모달에서도 끄고 닫기를 사용하게 만든다."
[결론]
header - cartModal - cart
1. 카트를 만들었다.
import styles from "./Cart.module.css";
function Cart(props) {
const { toggleModal } = props
const cartItems = cartItemInfo.map((item) => (
<div>
<li>
<div className={styles.item_info}>
<h2> {item.name}</h2>
<p> {item.price}</p>
</div>
<div className={styles.item_quantity}>
<div>
<label htmlFor={"number"}> 수량 </label>
<input
id={"number"}
type={"number"}
value={item.amount}
defaultValue={item.amount}
/>
</div>
<div>
<button onClick={cartItemAdd.bind(null, item.id)}> + </button>
<button onClick={cartItemRemove.bind(null, item.id)}> - </button>
</div>
</div>
</li>
<hr />
</div>
));
return (
<div className={styles.maindiv}>
<ul className={styles.cartItmes}>{cartItems}</ul>
<div className={styles.total_price}>
<span>Total Price</span>
<span> {cartCtx.totalPrice.toFixed(2)} </span>
</div>
<div className={styles.cart_buttons}>
<button> 주문</button>
<button onClick={toggleModal}> 닫기 </button>
</div>
</div>
);
}
export default Cart;
2. 카트를 createPortal 을 사용한, Modal 형태로 만들었다.
import Cart from "../../cart/Cart";
import { createPortal } from "react-dom";
import styles from "./Cart-Modal.module.css";
function CartModalContent(props) {
const { toggleModal } = props;
return <div className={styles.modal_background} onClick={toggleModal}></div>;
}
function CartModalBackgroundprops(props) {
const { toggleModal } = props;
return (
<div className={styles.modal_content}>
<Cart toggleModal={toggleModal} />
</div>
);
}
function CartModal(props) {
const { toggleModal } = props;
return (
<div className={styles.modal}>
{createPortal(
<CartModalBackgroundprops toggleModal={toggleModal} />,
document.getElementById("cart-modal-background")
)}
{createPortal(
<CartModalContent toggleModal={toggleModal} />,
document.getElementById("cart-modal-content")
)}
</div>
);
}
export default CartModal;
3. 실행할 곳은 Header 의 카트 버튼이다.
= 실제로 Modal , Show 함수의 시작점이다.
import { Fragment, useState, useContext } from "react";
import styles from "./layout-header.module.css";
import CartModal from "../modal/Cart-Modal";
import CartContext from "../../../store/Cart-Context";
function LayoutHeader() {
const [showModal, setShowModal] = useState(false);
const cartCtx = useContext(CartContext);
const totalItemAmount = cartCtx.itemInfo.reduce(
(acc, item) => +acc + +item.amount,
0
);
function toggleModal() {
setShowModal((prev) => !prev);
}
return (
<Fragment>
<ul className={styles.header}>
<li>
<h1>Logo</h1>
</li>
<li className={styles.cart} onClick={toggleModal}>
<svg
...
/>
</svg>
<h3>카트</h3>
<span> {totalItemAmount} </span>
</li>
</ul>
<div className={styles.header_image}>
<img src="/mainpage/meals.jpg" alt="main-background"></img>
</div>
{showModal && <CartModal toggleModal={toggleModal} />}
</Fragment>
);
}
export default LayoutHeader;
4. 렌더되는 곳은, Portal 에 의해, index.html 이다.
...
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="cart-modal-background"></div>
<div id="cart-modal-content"></div>
<div id="root"></div>
</body>
생각한점.
1. Context 를 사용하면 좋았겠다.
다만, 자주 누를 버튼이라 꺼려졌다.
2. 결국 Portal 을 써도, 불편하기는 매한가지 인듯 하다...
'공부용-사이드프로젝트 > React - 음식 주문기 프로젝트' 카테고리의 다른 글
4. Context 에서 "카트"의 "삭제" 로직을 추가해보자 with Array.splice() (0) | 2022.12.12 |
---|---|
3. 카트 내에서 context를 조작해보자. WITH function.bind() (0) | 2022.12.12 |
2. Context, useReducer 를 사용하여, 카트에 물건을 담아보자. (1) | 2022.12.12 |
댓글