개인과제를 하던 중 modal을 구현해야하는 부분이 있어 creatPortal을 사용하게 되었다.
portal을 사용하면 현재 컴포넌트를 DOM의 다른 위치에 삽입할 수 있어서 우리가 보는 'root' DOM이 아닌 다른 DOM에 등장하는 화면을 구현할 수 있다.
<div id='modal'>
Modal이 부모 컴포넌트에서 튀어나온 것처럼 보이는 것을 구현하기 위해 Modal이 보여지는 부분(Element)을 만들어야 한다.
public/index.html에는 id="root"인 div가 있는데 아래와 같이 작성해 id="modal"인 부분에 Modal을 띄울 것이다.
// components/modal/Modal.tsx
import ReactDOM from 'react-dom'
interface ModalProps{
showModal:boolean
closeModal:()=>void
}
const Modal = ({showModal,closeModal}:ModalProps)=>{
const modal = (
<aside>
<button onClick={closeModal}>close</button>
</aside>
)
const element = document.getElementById('modal')
return isShown ? ReactDOM.createPortal(modal,element as Element) : null
}
export default Modal
createPortal
은 ReactDOM의 API로 상위 요소 외부에 컴포넌트를 렌더링할 수 있다.
createPortal
은 인자를 두개 받는데 첫번째 인자는 렌더링할 component이고 두번째 인자는 첫번째 인자를 렌더링할 DOM의 위치이다.
// component/app/App.tsx
import Modal from './components/modal/Modal
const App = () => {
const [isShown, setShown] = useState(false)
const closeModal = () => setShown(prev=>!prev)
return (
<>
<main>
// jsx...
</main>
<Modal isShown={isShown} closeModal={closeModal} />
</>
)
}
export default App
이로서 모달의 구현이 완성되었다. Portal을 사용하지 않고 만들었을 때는 z-index를 비롯해 복잡하게 구현하던 것들이 단순해졌다.