react - Portal

박현·2023년 6월 18일
0

React

목록 보기
14/15

Portal

Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공한다.
리액트 포탈은 리액트 라이브러리에서 제공하는 기능 중 하나로, React 컴포넌트에서 DOM 트리 상에서의 위치를 변경할 수 있도록 해준다. 이 기능을 사용하면 컴포넌트의 렌더링 결과를 다른 DOM 노드로 이동시킬 수 있다.

< div id="root" >와 < div id="modal"> 은 형제 관계처럼 보이지만 실제로 modal은 root 안에서 보여지는 자식 컴포넌트이고,렌더링만 root의 바깥에서 이루어지고 있다.

Portal 생성방법

ReactDOM.createPortal(child, container)

첫 번째 인자(child)는 엘리먼트, 문자열, 혹은 fragment와 같은 어떤 종류이든 렌더링할 수 있는 React 자식이고, 두 번째 인자(container)는 DOM 엘리먼트이다.

장점

  1. 유연한 구성
    : 리액트 포탈은 컴포넌트를 다른 DOM 위치로 이동시키기 때문에 UI 구성을 더욱 유연하게 할 수 있다.
    예를 들어, Modal 창을 구현할 때 일반적으로는 모달 컴포넌트를 최상위 컴포넌트의 자식으로 추가해야 하는데 리액트 포탈을 사용하면 모달 컴포넌트를 원하는 위치로 이동시킬 수 있다. 복잡한 UI 구성을 쉽게 구현할 수 있다.

  2. 성능 최적화
    : 리액트 포탈은 컴포넌트의 렌더링 결과를 다른 DOM 위치로 이동시키는 기능을 제공하므로, 컴포넌트의 렌더링이 최적화될 수 있다.
    예를 들어, 상위 컴포넌트에서 자식 컴포넌트를 렌더링하면서 상태(State)를 변경하면, 해당 컴포넌트와 그 자식 컴포넌트가 모두 다시 렌더링된다.
    하지만 리액트 포탈을 사용하면 해당 컴포넌트와 자식 컴포넌트 중에서 변경된 부분만 렌더링되므로, 불필요한 렌더링을 최소화할 수 있다.

언제 사용하면 좋은가??

  1. 모달(Modal): 모달은 부모 컴포넌트의 스타일링 속성에 제약을 받아 z-index 등으로 번거로운 후처리를 해줘야한다.하지만 포탈을 사용하면 독립적인 구조와 부모-자식 관계를 동시에 유지하면서, z-index 등 부모 컴포넌트의 제약에서 벗어날 수 있다.

  2. 포탈(Portal): 포탈은 일반적으로 다른 웹 페이지로 이동하는 링크를 클릭할 때, 새로운 브라우저 탭이나 창을 열어서 해당 페이지를 보여주는 기능을 말한다. 이 기능을 구현할때 포탈을 사용해보자

구현 방법

  1. index.html에 모달이 렌더링될 위치를 잡아준다.
  <body>
    <div id="root"></div>
    <div id="modal"></div> // 모달이 렌더링 될 위치
  </body>
  1. Potal.js 생성
//modal div를 가져와 children으로 넣어주는 Portal역할을 할 Portal.js를 만들어준다.
import reactDom from "react-dom";

export const ModalPortal = ({ children }) => {
  const el = document.getElementById("modal");
  return reactDom.createPortal(children, el);
};
  1. modal 컴포넌트 생성

  2. modal을 사용할 컴포넌트에 Portal, Modal를 렌더링

//modal을 띄우려는 컴포넌트 파일
import ModalPortal from "../helpers/Portal";
import alertModal from "./defaultAlert1";

const Group = props => {
  const [modalOn, setModalOn] = useState(false);

  const handleModal = () => {
    setModalOn(!modalOn);
  };
  
  return (
    <>
       <button onClick={handleModal} className="btn_registReq">alert창 띄우기</button>
       <ModalPortal>
         {modalOn && <Modal onClose={handleModal} />}
       </ModalPortal>
    </>
  );
};

export default Group;

0개의 댓글