본문 바로가기
리액트

[react] 리액트 모달(modal) DOM tree, createPortal

by jaewooojung 2021. 3. 28.

ReactJS


createPortal

모달은 사용자에게 항상 최우선으로 출력되어야 하는 경우가 많습니다. react의 DOM tree를 보면, 모든 컴포넌트가 최상위 컨테이너인 root(<div id="root">)에 종속되는데, 모달의 경우에는 어느 컴포넌트에서 호출이 되어도 모든 컴포넌트 위에 존재합니다. 따라서 물리적인 구조상 root를 벗어나는 것이 더 깔끔할 수 있습니다.

 

모달 뿐만이 아니라 애플리케이션 내에서 리액트 코드를 부분적으로만 사용하는 경우에도 root 이외의 DOM tree를 구성해야 하는 경우가 있습니다. 이럴 때 createPortal을 사용하면 컴포넌트를 기존의 DOM tree에서 물리적으로 분리할 수 있습니다.

 

구문

react-dom 패키지의 createPortal을 사용해 줍니다.

createPortal(children, domNode, key?);
children 모달 컴포넌트
domNode 모달 컴포넌트를 종속시킬 루트 레벨의 요소

 

 

예시

1. root div와 같은 레벨에 <div id="modal"> 컨테이너를 추가해 줍니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <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="root"></div>
    <div id="modal"></div> <!-- 추가 -->
  </body>
</html>

 

 

2. 모달 컴포넌트에서 JSX를 반환할 때 createPortal을 사용합니다.

import { createPortal } from "react-dom";

function Modal(props) {
  const { message } = props;
  return createPortal(
    <div
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        position: "fixed",
        bottom: 30,
        left: 0,
        width: "100%",
        height: 50,
      }}
    >
      <div
        style={{
          width: "30%",
          textAlign: "center",
          borderRadius: 30,
          background: "grey",
          fontSize: 20,
          color: "white",
        }}
      >
        <p>{message}</p>
      </div>
    </div>,
    document.getElementById("modal")
  );
}

export default Modal;

createPortal로 DOM tree를 벗어나는 modal

 

이제 Modal 컴포넌트는 기존의 root 계층에서 분리되어 modal 컨테이너에 렌더링 됩니다. 단, 물리적인 위치만 분리되어 있을 뿐, 데이터나 이벤트 버블링 등의 논리적인 흐름은 root 내부에 있는 것과 동일합니다. 예를 들어 위 코드에서 Modal 컴포넌트가 받는 props는 여전히 해당 컴포넌트의 부모 컴포넌트에 의해서 전달됩니다. 



        
답변을 생성하고 있어요.