본문 바로가기
  • 삽질하는 자의 블로그
공부용-사이드프로젝트/React - 음식 주문기 프로젝트

1. Cart와 Modal, 그리고 Portal

by 이게뭐당가 2022. 12. 12.

카트를 누르면, 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 을 써도, 불편하기는 매한가지 인듯 하다...

댓글