본문 바로가기
react & next.js

React Portal로 모달 생성하기

by 고마드 2024. 1. 2.

https://react.dev/reference/react-dom/createPortal

 

리액트 포탈 없이 모달을 개발하게 되면 모달 컴포넌트가 한 부모 요소 안에 다른 컴포넌트와 함께 위치하게 된다. 이는 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