[React] Portal 사용 이유, 사용법을 알아보자 (Modal 예시)
[React] Portal 사용 이유, 사용법을 알아보자 (Modal 예시)
리액트 공통 모달을 만들기 위해 구글링을 해봤는데, 많은 사람들이 React Portal을 이용하여 모달을 만들었다. 처음 알게되어서 무엇인지 자세히 알아보도록 했다.
React Portal이란?
React Portal은 React의 일반적인 렌더링 흐름을 따르지 않고, 특정 DOM 노드에 컴포넌트를 렌더링할 수 있도록 하는 기능이다. ReactDOM.createPortal 함수를 사용하여 구현된다.
-
Portal은 기존의 DOM 구조를 따르지 않고 원하는 위치(보통 body 아래)에 렌더링할 수 있다. - 주로 모달, 툴팁, 드롭다운 메뉴 등의 UI 요소를 구현할 때 유용하다.
이전에 공통 모달을 만들 때 부모의 스타일에 영향을 받고 렌더링이 되는 위치도 일정하지 않아서 css 처리를 해줘야했는데 Portal의 경우 DOM 구조에 벗어나 별도의 위치에서 렌더링되므로, 스타일링이 훨씬 수월해지는 것 같다.
Portal 사용 방법
2-1) index.html 설정
index.html에서 Portal을 삽입할 DOM 요소를 생성해준다.
<body>
<div id="root"></div>
<!-- root 아래에 portal-modal 생성 --->
<div id="portal-modal"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
2-2) Portal을 사용한 컴포넌트 생성
ReactDOM.createPortal을 활용하여 특정 DOM 요소에 컴포넌트를 렌더링한다.
-
ReactDOM.createPortal(element, container)-
element: 렌더링할 JSX 요소 -
container: 해당 요소를 렌더링할 DOM 요소 (document.getElementById("portal-modal"))
-
import ReactDOM from "react-dom";
const Modal = ({ children }) => {
return ReactDOM.createPortal(
<div className="modalWrap">
<div className="modalCont">{children}</div>
</div>,
document.getElementById("portal-modal")
);
};
export default Modal;
2-3) 사용 및 확인
원하는 위치에 Modal컴포넌트를 넣어도 렌더링될 때 처음 index.html에 지정해줬던 위치에서 렌더링된다.
이벤트 버블링
Portal을 사용하면 부모 컴포넌트가 아닌 다른 DOM 위치에 렌더링되지만, React의 이벤트 버블링 특성은 유지된다. 즉, 부모 요소의 onClick 핸들러가 실행될 수 있다.
- 이를 방지하려면
event.stopPropagation()을 활용하자.
const Modal = ({ children, onClose }) => {
return ReactDOM.createPortal(
<div className="ModalWrap" onClick={onClose}>
<div className="ModalCont" onClick={(e) => e.stopPropagation()}>
{children}
</div>
</div>,
document.getElementById("portal-modal")
);
};
정리
-
React Portal은ReactDOM.createPortal을 사용하여 특정 DOM 요소에 컴포넌트를 렌더링할 수 있다. -
Portal을 활용하면 부모의 스타일 영향을 받지 않고 원하는 위치에 UI 요소를 렌더링할 수 있다. - 이벤트 버블링을 주의해야 하며,
stopPropagation()을 활용하여 해결할 수 있다.