[React] Portal을 활용해 Modal 창 만들기

고병표·2022년 2월 3일
0

React.js

목록 보기
10/21

Portal?

ReactDOM에서 제공하는 Portal은 컴포넌트를 렌더링 할 때, 부모 컴포넌트의 DOM 외부에 존재하는 DOM 노드에 렌더링 할 수 있게 해준다.

풀어서 설명하자면

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

즉, DOM의 계층구조 시스템에 종속되지 않으면서 컴포넌트를 렌더링 할 수 있다!

이 기능은 Modal 컴포넌트를 만들어야 될 때 매우 유용하게 사용 할 수 있다.

사용 방법

리액트 프로젝트 엔트리 파일인 index.js 부분에 "modal-root" 설정

  <body>
    <div id="root"></div>
    <div id="modal-root"></div>
  </body>
  • Modal.jsx 파일
import * as ReactDOM from 'react-dom'

const $portal = document.querySelector('#modal-root')

const Modal = ({ children, isShowing, close }) => {
  return isShowing && $portal
    ? ReactDOM.createPortal(
        <S.ModalWrapper className={'modal-container'} onClick={close}>
          <div className={'contents'}>{children}</div>
        </S.ModalWrapper>,
        $portal,
      )
    : null
}

export const ModalWrapper = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  background: rgba(0, 0, 0, 0.4); // 바깥 배경 밝기
  z-index: 10;
`



export default Modal
  • useModal Hook
import { useState } from 'react'

const useModal = (initShow = false) => {
  const [isShowing, setIsShowing] = useState(initShow)

  const toggle = (eventOrBool) => {
    if (typeof eventOrBool === 'boolean') {
      setIsShowing(eventOrBool)
      return
    }

    const target = eventOrBool.target

    if (target.closest('.close')) {
      setIsShowing(!isShowing)
      return // close 클릭시 종료
    }
    if (target.closest('.contents')) {
      return // 안 contents 클릭시 유지
    }
    setIsShowing(!isShowing) // 그 외 종료
  }

  return { isShowing, toggle }
}

export default useModal

코드참고
src > components > base > Modal

0개의 댓글