React portal

fieldnight·2025년 1월 10일
0
post-thumbnail

import { createPortal } from 'react-dom';
import styled from 'styled-components';
import usePortal from '../../hooks/usePortal';

const PortalContainer = ({ isVisible, id, children }) => {
  const target = usePortal(id);
  // 주어진 id로 포털 부모 요소를 얻음
  return createPortal(
    // React 내장 함수인 createPortal은 두 개의 인자를 받음.
    isVisible ? <Container>{children}</Container> : null, 
    // 1.렌더링할 컴포넌트
    target,
    // (포털의 부모 DOM 요소) 2. 타겟 돔 노드
  );
};
export default PortalContainer;
// 변수 선언 후 내보내기

const Container = styled.div`
  border: 1px solid black;
`;

React 포털은 React 컴포넌트 트리 바깥의 DOM 노드에 React 컴포넌트를 렌더링할 수 있게 해준다. 일반적으로 React 컴포넌트는 부모 컴포넌트의 DOM 구조 안에 렌더링되지만, 포털은 이를 무시하고 지정된 DOM 노드에 렌더링한다.부모 컴포넌트의 dom 구조에 영향을 주지 않는다. 즉, 모달, 드롭다운 같은 UI 컴포넌트를 구현할 때 유용하며, z-index와 CSS 레이아웃 문제를 피할 수 있다.

usePortal은 특정 id를 가진 DOM 노드를 반환하는 커스텀 훅이다.

id="modal-root"로 지정된 HTML 요소를 찾아서 포털의 렌더링 대상 노드로 사용한다.

ConfirmModal은 PortalContainer를 사용하여 모달을 렌더링한다.


export default function ConfirmModal({ isOpen, closeModal, onConfirm, ModalMessage }) {
  return (
    <PortalContainer isVisible={isOpen} id="modal-root">
      <ModalBackdrop onClick={closeModal} />
      <Container>
        <ModalText>{ModalMessage}</ModalText>
        <ButtonContainer>
          <ConfirmButton onClick={onConfirm}>확인</ConfirmButton>
          <CancelButton onClick={closeModal}>취소</CancelButton>
        </ButtonContainer>
      </Container>
    </PortalContainer>
  );
}
  1. PortalContainer는 usePortal(id)로 포털을 렌더링할 DOM 노드(modal-root)를 찾음.

  2. createPortal을 사용해 children을 modal-root에 렌더링.

  3. ConfirmModal은 PortalContainer를 감싸면서 UI(모달)를 구성.

0개의 댓글