React Portals

jaehan·2023년 3월 22일
0

React

목록 보기
32/33

Protal이 뭐고 왜쓸까?

public/index.html

<div id="root"></div>

index.html을 보면 root라는 id를 가진 div 태그가 있다.

이 div태그는 root DOM을 생성하고, src 폴더 내부의 react 코드를 추가해서 DOM Tree를 만든다.

src/index.js

ReactDOM.render(<App />, document.getElementById('root'));

src/index.js 파일에서 위의 코드로 App.js에서 작성한 코드를 root DOM에 넣어주는 것이다.

리액트에선 App 파일내부에 모든 코드를 넣기 때문에 App 컴포넌트가 전체의 부모가 된다.

근데 이 부모 컴포넌트로 부터 종속되지 않는 컴포넌트를 만들어야 할 때가 있다.
예를 들어 모달창이다.

그럴때 react portal을 이용해서 부모 컴포넌트 외부에 렌더링 시켜 분리된 컴포넌트를 개발 할 수 있다.

Portals

react 홈페이지에서는 아래와 같이 설명한다.
Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공합니다.

ReactDOM.createPortal(child, container)

사용법은 위 코드로 사용하고 매개변수는 아래와 같다.

  • child: ReactNode
  • container: Dom Element

📌 이 말은 child에 분리하고 싶은 컴포넌트를 넣고 container에 부모로 삼고 싶은 DOM을 넣어주면 된다는 말이다.

public/index.html

<div id="root"></div>
<div id="modal"></div>

src/ModalPortal.js

import ReactDOM from 'react-dom';

const ModalPortal = ({ children }) => {
  const el = document.getElementById('modal');
  return ReactDOM.createPortal(children, el);
};

export default ModalPortal;

📌 index.html의 modal DOM에 children(reactNode) 코드를 넣는다는 느낌이다.

src/MyModal.js

import React from "react";
import "./MyModal.css";

const MyModal = ({ onClose }) => {
  return (
    <div className="MyModal">
      <div className="content">
        <h3>모달</h3>
        <p>여기는 modal Dom</p>
        <button onClick={onClose}>Close</button>
      </div>
    </div>
  );
};

export default MyModal;

👆 ModalPortal children안에 넣을 modal 컴포넌트 이다.

src/App.js

import React, { Component, useState } from "react";
import MyModal from "./MyModal";
import ModalPortal from "./ModalPortal";
import "./App.css";

const App = () => {
  const [modal, setModal] = useState(false);

  const handleOpenModal = () => {
    setModal(true);
  };
  const handleCloseModal = () => {
    setModal(false);
  };

  return (
    <div className="App">
      <h1>여기는 root Dom</h1>
      <button onClick={handleOpenModal}>Open</button>
      {modal && (
        <ModalPortal>
          <MyModal onClose={handleCloseModal} />
        </ModalPortal>
      )}{" "}
    </div>
  );
};

export default App;

❗️ App 안에서 ModalPortal로 children 컴포넌트 묶어주면 이 컴포넌트는 modal DOM에 종속된 요소이다.

css

App.css
.App {
  text-align: center;
  color: #61dafb;
}

MyModal.css
.MyModal {
  background: rgba(0, 0, 0, 0.25);
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.MyModal .content {
  background: white;
  padding: 1rem;
  width: 400px;
  height: auto;
}

위 css 까지 적용해 주고 실행해 보면 아래처럼 잘 나온다

❓ 근데 이걸거면 걍 display:none 해놨다가 꺼내면 되는거 아닌가 라는 생각이 들었지만 css를 보면 다른 DOM이기 때문에 글자색이랑 가운데 정렬이 들어가지 않고 정해준 css 만 들어간걸 볼 수 있다.

👍 모달만들땐 이방식으로 만드는게 정답인것 같다.

참고: https://ko.reactjs.org/docs/portals.html
https://velog.io/@velopert/react-portals

0개의 댓글