일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- github
- 코드업
- git
- frontend
- cleancode
- HTML
- max-width
- coding
- 그럼에도 불구하고
- TypeScript
- node
- 프론트엔드
- 변수
- @media
- media query
- JS
- 그럼에도불구하고
- react-router-dom
- node.js
- 반응형 페이지
- react
- 자바문제풀이
- CSS
- redux
- JavaScript
- Servlet
- 자바
- 코딩테스트
- java
- webpack
- Today
- Total
그럼에도 불구하고
[React] Portal이란? 본문
오늘은 Portal에 대해 알아보겠습니다. :)
[ Portal ]
React 공식 문서에 따르면
Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링 하는 최고의 방법이라고 합니다.
현재 <div id ="root">와 <div class="ErrorModal_backdrop__iw-9R">은 부모 자식 관계로 속해있습니다.
[ 사용 이유 ]
일반적으로 react는 부모 컴포넌트가 렌더링 되면 자식 컴포넌트가 렌더링 되는 tree 구조를 가지고 있습니다.
하지만 때때로 이런 tree구조가 불편함을 가져다주기도 해서,
이럴 때 부모-자식 관계를 유지하지만 독립적인 위치에서 렌더링을 하면 훨씬 편리한 경우가 있습니다.
대표적인 예로 modal은 부모 컴포넌트의 스타일링 속성에 제약을 받아 z-index 등으로 번거로운 후처리를 해줘야합니다.
이러한 상황에서 portal을 통해 독립적인 구조와 부모-자식 관계를 동시에 유지할 수 있다면, z-index 등 부모 컴포넌트의 제약에서 벗어날 수 있습니다.
[ 구현 방법 ]
1. public/index.html에 Modal이 렌더링 될 위치 심어주기
1 2 3 4 5 | <body> <div id="backdrop-root"></div> <div id="overlay-root"></div> <div id="root"></div> </body> | cs |
portal을 구현할 tree의 부모 컴포넌트를 어디로 설정할지 정하는 것입니다.
위 코드에선 기존 최상단 요소인 root의 형제관계로 backdrop과 modal 요소를 넣었습니다.
이 요소에서 backdrop과 modal 컴포넌트가 렌더링 되도록 만들 예정입니다.
2. ErrorModal.js에서import reactDom from "react-dom" 설정하기
1 | import ReactDOM from "react-dom"; | cs |
3. ErrorModal.js에서 Backdrop div 만들기
1 2 3 | const Backdrop = (props) => { return <div className={classes.backdrop} onClick={props.onConfirm} />; }; | cs |
4. ErrorModal.js에서ModalOverlay 만들기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const ModalOverlay = (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> ); }; | cs |
만들던 파일에서 가져온 코드라 만드는 방식만 보시면 됩니다. :)
5. Backdrop, Modal을 띄울 컴포넌트에 Portal, Backdrop, Modal 조건부 렌더링
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const ErrorModal = (props) => { return ( <React.Fragment> {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") )} </React.Fragment> ); }; | cs |
backdrop와 modal을 렌더링 하고자 하는 컴포넌트 파일에서 Portal에 감싸진 형태로 backdrop과 modal을 넣어주면 됩니다.
물론 backdrop과 modal의 경우 계속 UI에 나타나면 안 되기에 다른 파일에서 마우스로 클릭 시 이를 제어할 수 있게 만들어줬습니다.
참고용 전체 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import React from "react"; import ReactDOM from "react-dom"; import Card from "./Card"; import Button from "./Button"; import classes from "./ErrorModal.module.css"; const Backdrop = (props) => { return <div className={classes.backdrop} onClick={props.onConfirm} />; }; const ModalOverlay = (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> ); }; const ErrorModal = (props) => { return ( <React.Fragment> {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") )} </React.Fragment> ); }; export default ErrorModal; | cs |
backdrop과 modal이 root와 분리되어 있는 것을 볼 수 있습니다.
'React > React basics' 카테고리의 다른 글
[React] useEffect란? (0) | 2023.04.07 |
---|---|
[React] useRef란? (0) | 2023.04.06 |
[React] htmlFor란? (0) | 2023.04.06 |
[React] Styled Component란? (0) | 2023.04.04 |
[React] state란? (0) | 2023.03.29 |