본문 바로가기
개발

React.createPortal

by FODI 2022. 9. 28.

자식 컴포넌트(button)에서 JSX 표현식을 return하면, 자식 컴포넌트는 아래의 콘솔창처럼 부모 컴포넌트(root)의 내부에서 렌더링이 발생한다.

 

일반적인 렌더링 상황

 

하지만 createPortal을 사용하면 자식 컴포넌트는 부모 컴포넌트에 종속되지 않고 다른 container 컴포넌트에서 렌더링을 할 수 있다. createPortal은 인자로 제공된 자식 컴포넌트 혹은 JSX 표현식을 부모 컴포넌트의 외부에서 렌더링하는 메서드이기 때문이다.

 

아래 콘솔창에 있는 <div class="modal-wrapper-root">엘리먼트와 <div id="root"> 엘리먼트는 형제 관계인 것처럼 보이지만, 실제 코드에서는 <div class="modal-wrapper-root">엘리먼트가 <div id="root"> 엘리먼트에 속한 부모 자식관계이다.

createPortal 메서드를 사용한 경우

 

실제 코드를 살펴보자.

function ToastNotiParent() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={handleButton}>on/off</button>
      <ToastNotiChild open={isOpen} className='test'>
        <div>test</div>
      </ToastNotiChild>
    </>
  )
};

 

function ToastNotiChild({ open, className, children }) {
  const modalLayout = useRef(null);

  if (!open) {
    return null;
  }

  return createPortal(
    <div ref={modalLayout} className={`modal-wrapper-root ${className}`}>
      <div className='toast-wrapper'>{children}</div>
    </div>,
    document.body
  )
};

 

createPortal 메서드는 DOM tree에서 자식 컴포넌트를 부모 컴포넌트의 DOM 계층 구조 밖에 존재하는 DOM 노드에서 렌더링시킨다. 그렇다면 createPortal 메서드를 사용할 때 Context나 이벤트 위임은 어떤 식으로 처리가 되는 것일까?

 

결론부터 말하자면 React 내에서 컴포넌트가 동작하는 로직(Context 혹은 이벤트 버블링과 캡쳐링 등)은 일반적인 부모 자식 관계와 동일하다.

 

React는 이 때도 Virtual DOM을 활용하는데, 자식 컴포넌트에서 사용한 Portal의 개념(createPortal 메서드의 흔적 또는 코드상 위치)은 React tree(Virtual DOM tree)에 남아있고, react-dom 라이브러리가 Virtual DOM과 실제 DOM을 비교할 때 실제 DOM tree에서 자식 노드의 렌더링 위치가 변경되는 것이다.

 

 

 

참고

React 공식문서(Portals)

React 공식문서(재조정)

React 공식문서(Virtual DOM과 Internals)

ReactJS Virtual DOM and Reconciliation - Explain Like I'm Five

Web: React Portal 알아보기

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

주소창에 google.com을 치면 발생하는 일  (0) 2022.10.12
MIME  (0) 2022.10.02
JSX  (0) 2022.09.28
React Context  (0) 2022.09.28
React Router v6  (0) 2022.09.25

댓글