티스토리 뷰

Frontend/react.js

[React] Portal

blueprint-12 2022. 10. 22. 22:10

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

 

댓글