공부 및 일상기록

[React] Portal 본문

개발/React

[React] Portal

낚시하고싶어요 2023. 1. 17. 07:31

Portal은 리액트 프로젝트에서 컴포넌트를 렌더링 하게 될 때, UI를 어디에 렌더링 시킬지 DOM을 사전에 선택하여 부모 컴포넌트의 바깥에 렌더링 할 수 있게 해주는 기능이다.

 

ModalPotal 만들면서 이해하기

1. Portal 렌더 노드 심어주기

public / index.html에 modal-root 심기

최상단 요소인 root와 형제관계인 modal-root 요소를 만들어 준다. 여기에 portal을 통해 모달 컴포넌트가 렌더링 된다.

 

2.ModalPortal.jsx 만들기

import { ReactDOM } from "react";

const ModalPortal = ({ children }) => {
  const modalRoot = document.getElementById("modal-root");
  return ReactDOM.createPortal(children, modalRoot);
};
export default ModalPortal;

Portal을 통해 modal-root에 child컴포넌트를 렌더링 해주는 container컴포넌트를 만들어 준다.

ReactDOM.createPortal()메서드로 렌더링 가능하며 인자는 렌더링할 컴포넌트, 타겟 노드 순으로 넣어준다.

 

3.ModalFrame.jsx만들기

import styled from "styled-components";
import ModalPortal from "./ModalPortal";

const ModalFrame = ({ children, setOnModal }) => {
  return (
    <ModalPortal>
      <Container onClick={() => setOnModal(false)}>
        <div>{children}</div>
        <button onClick={() => setOnModal(false)}>닫기</button>
      </Container>
    </ModalPortal>
  );
};
export default ModalFrame;

const Container = styled.div`
  z-index: 999;
  position: fixed;
  top: 0;
  left: 0;
  width: 500px;
  height: 500px;
  background-color: black;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  button {
    background-color: white;
  }
`;

 

4. TestModal.jsx만들기

import ModalFrame from "./ModalFrame";

const TestModal = ({ setOnModal }) => {
  return <ModalFrame setOnModal={setOnModal}>테스트 모달!</ModalFrame>;
};
export default TestModal;

 

5. Modal 조건부 렌더링 (onModal의 상태값으로 토글링한다. 여기에 따라 조건부 렌더링 된다.)

import React, { Component, useState } from "react";
import styled from "styled-components";
import "./App.css";
import TestModal from "./TestModal";

const App = () => {
  const [onModal, setOnModal] = useState(false);
  return (
    <div>
      <Btn1 onClick={() => setOnModal(true)}>모달창 열기</Btn1>
      {onModal && <TestModal setOnModal={(bool) => setOnModal(bool)} />}
    </div>
  );
};

export default App;

const Btn1 = styled.button`
  width: 400px;
  height: 80px;
  background-color: teal;
`;

 

 

모달창 만들기 완료!

모달이 구현되었다. 위 코드는 특정 컴포넌트에서 모달 렌더링 여부가 한정적으로 조회 및 제어 된다.

로그인과 같은 전역모달은 Redux나 Recoil과 같은 전역상태를 통해 렌더링 해야 할 것이며, 이러한 제어는 useModal() 훅으로 유용하게 구현할 수 있다.

 

 

portal과 render의 차이

구분 Portal Render
공통점 특정 DOM으로 컴포넌트를 렌더링
호출 위치 React Render 내부* 어디서든 가능
LifeCycle 호출한 부모 컴포넌트에 종속됨 새로운 생명주기로 관리됨
Unmount Lifecycle에 의해 언마운트됨 직접 ReactDOM.unmountComponentAtNode() 사용
event 실제 렌더링 위치는 다르나, 부모요소와 버블링/캡처링 가능 최상위 컴포넌트로 동작
활용 예시 특정 컴포넌트를 부모요소 외부에 렌더링하고자 할 때 React App을 새로 생성할 때

 

 

https://abangpa1ace.tistory.com/229

 

[React] Portal (포탈), Modal 구현하기

회사에서 선배와 React로 모달 구현에 대해 고민하다가 알게된 내용이었다. 우리 회사 프로젝트는 Vue를 사용하기 때문에, 플러그인(this.$modal) 메서드를 통해 루트에 모달 컴포넌트를 주입, 삭제해

abangpa1ace.tistory.com

 

 

'개발 > React' 카테고리의 다른 글

[React] Client-Side Routing  (0) 2023.01.17
[React] useMemo와 useCallback (feat React.memo와 차이점)  (1) 2023.01.17
[React] Memoization  (0) 2023.01.17
[React] React.Fragment  (0) 2023.01.17
[React] HOC에 대해 설명  (0) 2023.01.17