[React] Portal
Portal 이란?
리액트에서는 root element에 모든 컴포넌트를 올리고 지우고 반복하면서 컴포넌트를 만들었습니다.
포탈은 루트 외의 요소에 컴포넌트를 띄울 수 있게 해줍니다.
공식문서에 따르면 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법이라고 합니다.
div id="root 인 요소와 div id="portal"인 요소는 형제 관계처럼 보이지만 실제로 portal은 root안에서 보여지는 자식 컴포넌트이고, 렌더링만 root의 바깥에서 이뤄지고 있는 것입니다.(리액트의 tree구조가 리렌더링을 발생시키므로 이럴 때, 부모-자식 관계를 유지하면서 독립적인 위치에서 렌더링을 하면 편리한 경우에 사용, 부모 컴포넌트의 제약에서 벗어나기 위함)
*root element는 index.js 에 있는 이 친구를 말하는데,
const root = ReactDOM.createRoot(document.getElementById("root"));
진짜 root가 있는 곳은 public폴더의 index.html(SPA이니까 하나의 html이 존재하겠죠?) <div id="root"></div>
이 친구를 가져온 것입니다.
사용법
ReactDOM.createPortal(child, container)
- 첫 번째 인자(child): 엘리먼트, 문자열, 혹은 fragment와 같은 어떤 종류이든 렌더링할 수 있는 React 자식
- 두 번째 인자(container): DOM 엘리먼트(진짜 돔!!)
포탈 적용해보기
1. public/index.html 에 <div id="portal"></div> 를 추가해주고
2. 컴포넌트를 새로 만들거나 원래 컴포넌트 js파일에 새로운 Portal용 함수를 만들어줍니다.
저는 따로 컴포넌트를 만들어줬습니다.
- createPortal 메소드를 react-dom에서 임포트 해오고
- createPortal(자식 컴포넌트, 실제 돔 요소 container) //우리가 1번에서 id가 portal인 div요소를 만들어뒀으니 그곳으로 두번째 인자를 지정해주면 되겠습니다.
src/ReactPortal.js
import React from "react";
import { createPortal } from "react-dom";
// 포탈은 dom도 건들여야 하기 때문에 react-dom에서 createPortal을 가져옵시다.
function ReactPortal({ children }) {
return createPortal(children, document.getElementById("portal"));
}
export default ReactPortal;
3. 이렇게 만들어진 ReactPortal 이라는 컴포넌트를 사용하고자 하는 컴포넌트 파일에 불러와 자식 요소로 엘리먼트를 내려주면 내용이 렌더링되는 것을 확인할 수 있습니다.
src/App.js
<ReactPortal>
<p>안녕하세요</p>
</ReactPortal>
Portal은 모달창을 만들 때 유용하게 사용할 거 같습니다.
useState로 모달의 상태 true, false 값을 조절하고 state값이 true일 때만 modal이 렌더링하도록 조건을 걸어주면 모달창을 원하는 때에 띄워줄 수 있습니다. 공식 문서에 Portal이 왜 필요한 지에 대한 내용이 나와있으니 읽어보는 것을 추천드립니다.
https://ko.reactjs.org/docs/portals.html
Portals – React
A JavaScript library for building user interfaces
ko.reactjs.org