React에서 제공하는 Portal은 UI를 어디에서 렌더링 시킬지 DOM을 사전에 선택하여 부모컴포넌트 바깥에서 렌더링 할 수 있도록 해줍니다.
ReactDOM.createPortal(child, container)
react프로젝트의 html에서 기본적으로 제공하는 index.html
에서 코드를 추가합니다.
// index.html
<div id="root"></div>
<div id="modal"></div> // id가 modal인 div추가
두번째 인자에는 DOM오브젝트가 들어가야 하므로 첫번째 단계에서 만들었던 id인 modal을 참조합니다.
// ModalPortal.js
import ReactDOM from "react-dom";
const ModalPortal = ({ children }) => {
const el = document.getElementById("modal");
return ReactDOM.createPortal(children, el);
};
export default ModalPortal;
자신이 사용하고자 하는 모달 컴포넌트를 만들어줍니다.
// Modal.js
import React from "react";
import "./Modal.css";
const Modal = ({ onClose }) => {
return (
<div className="Modal">
<div className="content">
<h3>모달</h3>
<p>궁시렁 궁시렁</p>
<button onClick={onClose}>닫기</button>
</div>
</div>
);
};
export default Modal;
.Modal {
background: rgba(0, 0, 0, 0.25);
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.Modal .content {
background: white;
padding: 1rem;
width: 400px;
height: auto;
}
사용하고자 하는 컴포넌트에서 ModalPortal
를 이용해 Modal
을 감싸 자식 컴포넌트로 만들면 Portal 적용이 완료됩니다.
import React from "react";
import MyModal from "./MyModal";
import ModalPortal from "./ModalPortal";
import "./App.css";
const App = () => {
const [modal, setModal] = React.useState(false);
const handleCloseModal = () => {
setModal(false);
};
const handleOpenModal = () => {
setModal(true);
};
return (
<div className="App">
<h1>React Portals</h1>
<button onClick={handleOpenModal}>모달 열기</button>
{modal && (
<ModalPortal>
<MyModal onClose={handleCloseModal} />
</ModalPortal>
)}
</div>
);
};
export default App;