최대 1 분 소요

createPortal을 이용해 모달 만들기

📌createPortal이란?

  • 일부 자식들을 DOM의 다른 부분으로 렌더링할 수 있는 기능을 제공합니다.
  • 이벤트 버블링 문제를 해결할 수 있습니다.
  • z-index 관리가 편합니다.



📌createPortal로 모달 만들기

index.html

모달이 root에 있는 요소들 보다 위에 있어야 하므로 root 다음 줄에 modal 요소를 생성해줍니다.

<body class="darkmode lightmode">
  <div id="root"></div>
  <div id="modal"></div>
  <script type="module" src="/src/main.tsx"></script>
</body>


Modal.tsx

import React, { MouseEvent, useEffect } from "react";
import { createPortal } from "react-dom";
import * as S from "@/components/common/modal/Modal.style";

const portalElement = document.getElementById("modal") as HTMLElement;

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  children?: React.ReactNode;
}

const Modal = ({ isOpen, onClose, children }: ModalProps) => {
  useEffect(() => {
    document.body.style.overflow = isOpen ? "hidden" : "auto";
  }, [isOpen]);

  if (!isOpen) return null;

  const handleModalContainerClick = (event: MouseEvent<HTMLDivElement>) => {
    event.stopPropagation();
  };

  return createPortal(
    <>
      <S.BackDrop onClick={onClose} />
      <S.ModalContent onClick={handleModalContainerClick}>
        {children}
      </S.ModalContent>
    </>,
    portalElement
  );
};

export default Modal;


사용예시

import React, { useState } from "react";
import Modal from "./components/common/Modal";

const App = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsModalOpen(true)}>Open Modal</button>
      <Modal isOpen={isModalOpen}>
        <div>
          <h2>모달 제목</h2>
          <p>모달 내용</p>
          <button onClick={() => setIsModalOpen(false)}>Close Modal</button>
        </div>
      </Modal>
    </div>
  );
};

export default App;

댓글남기기