다음은 리액트 공식 문서에 명시된 createPortal 기본 코드이다.
<div>
<SomeComponent />
{createPortal(children, domNode, key?)}
</div>
포탈을 생성하기 위해서, JSX와 포탈이 렌더링 되야하는 DOM node를 매개 변수로 전달해야 한다.
import { createPortal } from 'react-dom';
// ...
<div>
<p>This child is placed in the parent div.</p>
{createPortal(
<p>This child is placed in the document body.</p>,
document.body
)}
</div>
위 코드에서 createPortal 에 JSX인 <p>This child is placed in the document body.</p> 를 첫번째 매개 변수로 지정했고, DOM node인 document.body 를 두 번째 매개변수로 지정했다.
따라서 document.body 에 해당하는 부분에 첫 번째 매개변수인 JSX가 렌더링 될 것이다. 포탈은 렌더링된 요소의 물리적 위치만 바꾸고, 그 요소가 React 애플리케이션 내부에서 어떻게 동작하는지(부모-자식 관계, 컨텍스트 접근 등)는 그대로 유지한다.
본 프로젝트에서 모든 페이지의 우측 하단의 채팅 버튼을 클릭하면 모달창이 열리게 하였다. 구현 화면은 맨 위와 같다. 다음은 코드 작성 과정이다.
createPortal 의 두 번째 매개변수인 DOM node는 document.getElementById() 등으로 접근 가능한 실제로 존재하는 요소여야 한다. index.html 의 body에 modal이라는 id를 가진 DOM node인 div를 작성했다.
<body>
<div id="root"></div>
<div id="modal"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
createPortal 코드 작성
리액트 공식 문서의 createPortal 기본 사용법을 참고해 페이지의 우측 하단에 있는 ChatButton 의 클릭 이벤트가 활성화되면 useState를 통해 open으로 바꿔 createPortal 함수가 실행되도록 하였다. 첫 번째 파라미터는 JSX 요소인 컴포넌트 <ChatModal /> 이고 두 번째 파라미터는 index.html 에서 설정한 DOM node 인 id가 ‘modal’인 div 이다.
ChatModal) 꾸미기
createPortal 의 첫 번째 파라미터이자 실질적인 모달창 화면으로 보여질 ChatModal 컴포넌트이다.

position: fixed는 요소를 뷰포트(viewport)에 상대적으로 고정시키다. 즉, 스크롤과 상관없이 항상 화면의 같은 위치에 있게 한다. top, bottom, left, right 속성을 모두 0으로 지정해 요소를 뷰포트 전체를 차지하게 만들었다. 그 후 display: flex를 와 align-items와 justify-content를 center로 지정하여 뷰포트 가운데에 모달창을 고정시켰다.