리액트 포탈 없이 모달을 개발하게 되면 모달 컴포넌트가 한 부모 요소 안에 다른 컴포넌트와 함께 위치하게 된다. 이는 z-index 사용 시 문제가 될 수 있다. z-index 1 안에 있는 요소의 z-index를 아무리 높여줘도 z-index가 2인 모달 위로 올라오지 않는 문제!
<div id="root">
<div style="z-index: 1;">
<div style="z-index: 1000;"></div>
</div>
<div id="modal" style="z-index: 2;"></div>
</div>
React Portals
Portals는 부모 컴포넌트 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링 할 수 있게 해 준다.
사용방법
- Container를 생성해준다.
layout.jsx
<body>
<div id="root"></div>
<div id="portal"></div>
</body>
- createPortal을 이용해 모달 컴포넌트를 만든다.
const Modal = ({ isOpen, children, onClose }) => {
if (!isOpen) return null;
return ReactDOM.createPortal(
<>
<div className="overlay" />
<div className="modal">
<button className="modal-close-btn" onClick={onClose}>닫기</button>
{children}
</div>
</>,
document.getElementById('portal')
)
}
이렇게 해주면 z-index와 관계없이 모달이 나온다.
주의사항
createPortal을 사용하면 이벤트 버블링(자식 요소에서 발생한 이벤트가 부모로 전달되는 것)이 가능하다. 모달 컴포넌트 사용 시 모달 컴포넌트의 부모 요소에 있는 이벤트 핸들러를 확인해서 의도된 대로 동작할 수 있게 해야 한다.
<div onClick={() => console.log('modal clicked')}>
<button onClick={() => setIsModalOpen(true)}>open modal</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>모달 children</Modal>
</div>
✔️ 리액트 공식 다큐먼트로 Portal 알아보기
https://react.dev/reference/react-dom/createPortal
createPortal – React
The library for web and native user interfaces
react.dev
'react & next.js' 카테고리의 다른 글
기존 Next.js Javascript프로젝트에 Typescript 도입하기 (0) | 2024.01.01 |
---|