[React]Porals에 대해 알아보자

rondido·2022년 11월 21일
0

React

목록 보기
17/40
post-thumbnail

React 관련 강의 영상을 보고 정리한 내용

Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공

ThankyouDialog.jsx

import React from 'react'
import Dialog from './Dialog'

export default function ThankyouDialog() {
  return (
    <div>
        <Dialog title={<h1 style={{
            color:"purple"
        }}> Thanks</h1>} description="It is honor to meet you" button={<button style={{backgroundColor:"blue", color:"white"}}>close</button>}>

        </Dialog>
    </div>
  )
}

Dialog.jsx

import React, { useState } from 'react'

export default function Dialog(props) {
    const [isOpen,setIsOpen] = useState(false);
    return (
        <div>
            <button onClick={()=>setIsOpen(true)}>Open</button>
            {isOpen && <div 
             style={{
                    position:"absolute",
                    zIndex:99,
                    top:"50%",
                    left:"50%",
                    transform:"translate(-50%,-50%)",
                    border:"1px solid black",
                    padding:24,
                    backgroundColor:"white",
                }}>
                    {typeof props.title === "string" ? (<h1>{props.title}</h1>) : props.title}
                    {typeof props.description === "string" ? (<h5>{props.description}</h5>) : props.description}
                    {typeof props.button === "string" ? (<button style={{backgroundColor:"red", color:"white"}} onClick={() => setIsOpen(false)}>{props.button}</button>) : <div onClick={()=>setIsOpen(false)}>{props.button}</div>}
                </div>
                }
                {isOpen && <div style={{
                    position:"fixed",
                    top:0,
                    left:0,
                    bottom:0,
                    right:0,
                    backgroundColor:"lightgray"
                }}>
                </div>}
        </div>
    )
}

Example.jsx

import React from 'react'
import ThankyouDialog from './ThankyouDialog'

export default function Example() {
  return (
    <div>
        <ThankyouDialog/>
        <div style={{position:'absolute'}}>
            <button>하하하하하</button>
        </div>
        
    </div>
  )
}

Dialog를 z-index를 주어 띄워지게 만들어 놧지만 위 코드를 실행시에는 button이 가려지지 않고 모달창이 따로 나타난다.

import React from 'react'
import ThankyouDialog from './ThankyouDialog'

export default function Example() {
  return (
    <div>
        
        <div style={{position:'absolute'}}>
            <button>하하하하하</button>
        </div>
        <ThankyouDialog/>
    </div>
  )
}

하지만 ThankyouDialog 코드를 아래로 내리면 버튼이 안보이는 걸 알 수 있다.

현재는 하나의 부모 컴포넌트 안에서 가지고 있어 위치를 내가 임의로 바꾸어서 조정할 수 있지만 어느 컴포넌트에 n번째 자식을 가지고 있다면 순차적으로 가지고 있는 UI의 스택을 벗어날 수 없게 된다.

다시 아까처럼 ThankyouDialog코드를 위에 올린 다음
public 폴더 안에 있는 index.html파일안으로 가서
<div id="portal"></div> 을 생성

<noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="portal"></div>

Example.jsx 아래와같이 수정

import React from 'react'
import { createPortal } from 'react-dom'
import ThankyouDialog from './ThankyouDialog'

const Protal = (props) =>{
    return createPortal(props.children, document.getElementById('portal'))
}
export default function Example() {
  return (
    <div>
        
        <ThankyouDialog/>
        <div style={{position:'absolute'}}>
            <button>하하하하하</button>
        </div>
    </div>
  )
}

Open이라는 버튼이 '하하하하' 버튼으로 인해 가려지기 때문에 Open 버튼에 css를 추가

Dalog.jsx

<button style={{position:'absolute',left:100}} onClick={()=>setIsOpen(true)}>Open</button>

이런 행위 들로 인해 portal라는 div 태그가 root태그의 stack을 넣어나 최상위가 되어 오픈 버튼 클릭 시 '하하하하' 버튼을 가리게 된다.

profile
함께 성장하는 것을 좋아하는 프론트엔드 개발자

0개의 댓글