Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공합니다.
overflow: hidden대화 상자를 불러오는 구성 요소가 대화 상자를 방해하는 컨테이너 또는 다른 스타일 안에 있더라도 포털을 사용하여 페이지의 나머지 부분 위에 떠 있는 모달 대화 상자를 만들 수 있습니다.
portals의 일반적인 사용 사례는 부모 컴포넌트가 overflow: hidden 이나 z-index 스타일을 가지지만, 자식이 컨테이너에서 시각적으로 “이탈해야 하는” 경우입니다. 예를 들어, 다이얼로그나, 호버카드나, 툴팁같은 게 있습니다.
그간 modal은 각 컴포넌트에서 상황에 따라 불러와 해당 컴포넌트내부에서 자식으로 직접 배치하여 사용했다.
index.html의 매우 깊숙한 곳에 자리잡고 있을 것이고, 부모요소의 css 스타일이 적용될 수도 있기 때문에 성능상 좋지 않은 방법이다.
portal을 사용하면 DOM 트리의 다른 위치에 렌더링할 수 있기때문에, modal등의 컴포넌트들을 어떠한 컴포넌트의 자식요소로 배치할 필요가 없게 된다.
스터디를 하면서 portal의 개념을 처음으로 알게 되었고 이를 사용한 후기를 기록해보자.
index.html에서 모달컴포넌트가 렌더될 id="overlays"인 div를 만들어둔다.
import ReactDOM from 'react-dom';
import classes from './Modal.module.css';
const Backdrop = (props) => {
return <div className={classes.backdrop} />;
};
const ModalOverlay = (props) => {
return (
<div className={classes.modal}>
<div className={classes.content}>{props.children}</div>
</div>
);
};
const portalElement = document.getElementById('overlays');
const Modal = (props) => {
return (
<>
{ReactDOM.createPortal(<Backdrop />, portalElement)}
{ReactDOM.createPortal(
<ModalOverlay>{props.children}</ModalOverlay>,
portalElement
)}
</>
);
};
export default Modal;
위와 같이 modal 컴포넌트 내부를 구성한다.
root말고 overlays에 모달이 렌더된다.
react 18버전에서는 react-dom에서 createPortal 훅을 지원하기 때문에
아래와 같이 변경할 수 있다.
import ReactDOM from "react-dom";
import { createPortal } from "react-dom"; //변경
import classes from "./Modal.module.css";
const Backdrop = (props) => {
return <div className={classes.backdrop} />;
};
const ModalOverlay = (props) => {
return (
<div className={classes.modal}>
<div className={classes.content}>{props.children}</div>
</div>
);
};
const portalElement = document.getElementById("overlays");
const Modal = (props) => {
return (
<>
{createPortal(<Backdrop />, portalElement)} //변경
{createPortal(
<ModalOverlay>{props.children}</ModalOverlay>,
portalElement
)}
</>
);
};
export default Modal;
사용방법은 굉장히 간단한데 얻는 이점이 굉장히 많을 것으로 생각된다.
현재 프로젝트를 리팩토링 하면서 modal을 portal로 변경해보는 것으로 더 연습을 해보면 좋을 것 같다.
portal 관련 react 공식문서 https://react.dev/reference/react-dom/createPortal