[React] ReactDOM.createPortal() 작업하기

SuamKang·2023년 7월 7일
1

React

목록 보기
15/34
post-thumbnail
post-custom-banner

리액트 작업을 진행할때

createPortal 메소드는 리액트의 react-dom 라이브러리에 있는 기능으로, 리액트 애플리케이션의 컴포넌트 트리 외부에 자식 요소를 렌더링하는 데 사용된다.

일반적으로 리액트 컴포넌트는 자신이 속한 컴포넌트 트리 내에서만 렌더링되지만, createPortal을 사용하면 자식 요소를 다른 DOM 요소 내에 렌더링할 수 있다.

활용


보통은 아래와 같은 상황에서 포탈작업을 활용할 수 있다.

  1. 모달 또는 팝업 창과 같은 오버레이 컴포넌트: 일반적으로 모달은 애플리케이션의 컴포넌트 트리의 일부가 아니라 별도의 레이어에 표시된다. createPortal을 사용하면 모달 컴포넌트를 애플리케이션의 레이아웃에서 분리하여 렌더링할 수 있다.


  2. z-index 조절이 필요한 경우: createPortal을 사용하면 자식 요소를 다른 DOM 요소의 z-index 값에 따라 렌더링할 수 있다. 이를 통해 오버레이, 드롭다운 메뉴 등과 같은 요소를 화면의 다른 요소 위에 정확하게 배치할 수 있다.


1번의 경우에서 모달과 같은 오버레이 컴포넌트를 사용하게 될때 어떻게 적용되는지 코드로 살펴보면 아래와 같다.

index.html

    ...
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="backdrop-root"></div>
    <div id="overlay-root"></div>
    <div id="root"></div>
  </body>
    ...

보통은 "root"DOM 요소안에서 모든 앱 컴포넌트들이 렌더링되는 위치이지만 나중에 지정된 모달이나 백드롭에 해당하는 요소를 저위치에서 포탈을 이용해 렌더링되게 하기위해 포인터를 지정한다.

Modal.js

import ReactDOM from "react-dom";

import Button from "./Button";
import Card from "./Card";

import styles from "./Modal.module.css";

// ReactDOM.createPortal을 이용한 포탈만들기
const BackDrop = (props) => {
  return <div className={styles["modal-backDrop"]} onClick={props.onToggle} />;
};

const ModalOverlay = (props) => {
  return (
    <Card className={styles["modal-container"]}>
      <div onClick={(event) => event.stopPropagation()}>
        <header className={styles["modal-title"]}>
          <h2>{props.title}</h2>
        </header>
        <div className={styles["modal-content"]}>
          <p>{props.message}</p>
        </div>
      </div>
      <footer>
        <Button type="button" onClick={props.onToggle}>
          Okay
        </Button>
      </footer>
    </Card>
  );
};


function Modal(props) {
  return (
    <>
      {ReactDOM.createPortal(
        <BackDrop onToggle={props.onToggle} />,
        document.getElementById("backdrop-root")
      )}
      {ReactDOM.createPortal(
        <ModalOverlay
          title={props.title}
          message={props.message}
          onToggle={props.onToggle}
        />,
        document.getElementById("overlay-root")
      )}
    </>
  );
}

export default Modal;

ReactDOM.createPortal()의 첫번째 인자로는 렌더링되어야하는 리엑트노드 즉 컴포넌트를 지정해주고, 두번째인자엔 첫번째인자의 컴포넌트가 실제 렌더링될 DOM위치의 요소를 가리키는 포인터이다. 따라서 실제 DOM요소에 접근하기 위해 브라우저에서 제공하는 API를 적용해준다.

따라서 위 예시의 Modal컴포넌트는 'createPortal'을 사용해 각각 정의해준 'BackDrop'컴포넌트와 'ModalOverlay'컴포넌트들을 각각 'backdrop-root' 과 'overlay-root'라는 DOM요소에 렌더링 하게된다.

즉 모달 컴포넌트가 자체적으로 렌더링되지않고, 별도의 DOM요소 내에 렌더링 되는걸 볼 수 있다.



이렇게 포탈을 이용해 DOM조작을 진행하게 되면 개발자 도구에서 해당 이벤트가 발생할때, 지정해준 컴포넌트가 root요소 바깥 body태그의 직계자식으로 위치하여 렌더링 되는 모습을 확인할 수 있다.

주의

포탈은 주로 DOM 조작이 필요한 상황에서 유용하게 사용이 되고 의미론적으로 더 정확한 HTML코드를 쓸 수 있게 되지만, 남용하거나 오용하는 경우 컴포넌트 구조를 복잡하게 만들 수 있으므로 필요한 경우에만 사용하는 것이 좋을것 같다는 생각이다.

profile
마라토너같은 개발자가 되어보자
post-custom-banner

0개의 댓글