본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 101~200

# 113 [udemy React 완벽 가이드 노트] React Portal 모달창 중첩되지 않은 DOM에 렌더링 하기

목표 


 

 

목표는 위 사진과 같음.

root 엘리먼트 안에 깊이 중첩되지 않게 

ReactModal창의 엘리먼트를 따로 넣어주기

 

이렇게 하는 이유 (createPortal 을 쓰는 이유)


 

출처 블로그 : 

https://medium.com/hcleedev/web-react-portal-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-f00a48157862

 

 

 

Web: React Portal 알아보기

Modal, Tooltip 등에 주로 사용되는 React Portal에 대해 알아보자

medium.com

 

즉, 부모 컴포넌트의 스타일의 영향을 받지 않고 쓸 수 있기 때문에

사용하는 거라고 위 블로그를 참고하여 정리한다.

 

또한 강사는 이렇게 설명했다. 

Modal창이 위로 튀어나와 있는데, 

이걸 card클래스 안에 중첩되어 깊숙이 들어있으면 

의미적으로 맞지 않아 보인다는 의미다.

 

더 시맨틱한 HTML코드 작성을 위해서라도 React Portal로 작성하는 편이 좋아 보인다.

 

 

 

 

 

1. index.html 파일의 body에 id를 이용해 이 장소를 찾아올 수 있게 한다.


index.html 파일 중 일부

<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="backdrop-root"></div>
    <div id="overlay-root"></div>
    <div id="root"></div>
</body>
 

루트를 여러개 만들어서 여러 컴포넌트들이 포털되도록 한다.

 

 

2.  ErrorModal.js에 가서 어딘가에 포탈되어야 한다고 알려주기


동일한 파일에 추가할 것인데 모달과 함께 사용만 할 것이므로 문제 없다.  

그러나 다른 컴포넌트와 함께 사용할 것이면 개별파일로 나누어도 된다. 

 

 

 (1) ErrorModal.js파일의 jsx코드를 두개의 개별 컴포넌트로 나누기 

 

const Backdrop = props => {
  return <div className={classes.backdrop} onClick={props.onConfirm}></div>;
};

const MadalOverlay = props => {
  return (
    <Card className={classes.modal}>
      <header className={classes.header}>
        <h2>{props.title}</h2>
      </header>
      <div className={classes.content}>
        <p>{props.message}</p>
      </div>
      <footer className={classes.actions}>
        <Button onClick={props.onConfirm}>Okay</Button>
      </footer>
    </Card>
  );
};

 

(2)  react-dom을 import해준다 

(3) createPortal 메소드를 호출한다

 

(4)createPortal의 인자 :

  -렌더링되어야 하는 리액트 노드(jsx코드)

  -이 요소가 렌더링 되어야 하는 실제 DOM컨테이너를 가리키는 포인터 

 

const ErrorModal = props => {
  return (
    <>
      {ReactDOM.createPortal(
        <Backdrop onConfirm={props.onConfirm} />,
        document.getElementById("backdrop-root")
      )}
      {ReactDOM.createPortal(
        <ModalOverlay
          title={props.title}
          message={props.message}
          onConfirm={props.onConfirm}
        />,
        document.getElementById("overlay-root")
      )}
    </>
  );
};