React 와 Portal

JJ_Dean·2022년 12월 29일
0

React

목록 보기
10/14
post-thumbnail

Portal 이란?

쓰는 이유

예를 들어 다음 사진처럼 팝업창을 띄웠다.

이 팝업창을 띄운 페이지의 구성 조직도를 보자면

정보 입력 페이지 요소 안에 ➡
팝업창이 띄워져 있을 떄 입력창 접근을 막기 위한 어두운 커튼
+ 팝업창

이렇게 입력 페이지 안에 팝업창과 관련된 요소들이 포함되어 있다.

사용자 입장에서 생각해보면 이 팝업창은 모든 요소 위에 존재한다. 구조적으로 모든 요소 위에 존재해야될 팝업창이 정보 입력 페이지 안의 요소로 존재한다.

또 추후에 side drawer, dialog 같은 기능같이 오버레이 관련 컴포넌트를 제작하면 이와같은 방법으로는 예기치 못한 문제를 일으킬 수 있다고 한다.

이런 문제를 해결하고자 React 에서는 Portal 이라는 기능으로 오버레이처럼 항상 위에 존재해야 하는 컴포넌트를 body, 루트 div 최상위 위치 등 여러 곳으로 옮길 수 있게 한다.

쓰는 방법

Backdrop은 팝업창 뒤에 존재하여 그 뒤에 있는 요소들에 접근하는 것을 막고 팝업창을 더 돋보이게 하는 컴포넌트이다.

const ErrorModal = (props) => {
  return <Backdrop onClick={props.onConfirm} />;
};

위 코드는 렌더링되면 CSS 스타일링 덕분에 자신의 역할을 할 수 있지만 자신의 역할을 할 수 있더라도 다른 요소 안에 존재하기 때문에 예측하지 못한 오류가 생길 수 있다.

이 backdrop요소에 Portal을 적용해보자.

// index.html
<body>
  <div id="backdrop-root"></div>
  <div id="root"></div>
</body>

index.html은 React 컴포넌트를 읽으면서 렌더링하는 root 요소가 있는 곳이다.
index.html의 root div 옆에 "backdrop-root"를 id로 가진 div를 만들었다.

다음은 Portal을 적용하여 작성한 코드이다.

import ReactDom from 'react-dom';

// portal 준비
const PortalBackdrop = (props) => {
  return <Backdrop onClick={props.onConfirm} />;
};

const ErrorModal = (props) => {
  return (
    <React.Fragment>
      {ReactDom.createPortal(
        <PortalBackdrop onConfirm={props.onConfirm} />,
        document.getElementById('backdrop-root')
      )}
    </React.Fragment>
  );
};

Portal을 사용하는 방법은 다음과 같다.

ReactDom.createPortal(리액트 노드, 렌더링 할 위치(포인터))

리액트 노드는 렌더링 되어야 할 요소인 Backdrop을 return 하는 PortalBackdrop이다.
렌더링 할 위치(포인터)는 index.html에 추가한 "backdrop-root"를 id로 가진 div이다.

적용 후, 결과

위에서 만든 레이아웃(backdrop)이 나오기 전에는 backdrop-root div가 비어있다가

레이아웃이 적용된 후에는 backdrop-root div 안에 레이아웃으로 이동했다.

profile
공부하고 내 것으로 만들자.

0개의 댓글