일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 깃
- 코딩독학
- web
- github
- react
- 웹디자인기능사
- JavaScript
- git
- 리액트
- PROJECT
- 코드공유
- 연산자
- HTML
- 타입스크립트
- 실기
- 정보처리기사
- 웹디자인기능사실기
- 자바스크립트
- 프론트엔드
- 슬라이드전환
- Supabase
- JS
- CSS
- jQuery
- 생활코딩
- 웹디실기
- 렛츠기릿자바스크립트
- 세로메뉴바
- 웹퍼블리셔
- 비전공자
- Today
- Total
코딩하는라민
[React] React Portal 사용하기 본문
[React] React Portal 사용하기
Portal 이란?
리액트의 `Portal` 은 리액트 애플리케이션에서 DOM 트리의 다른 위치로 자식 요소를 렌더링하는 기능을 제공한다.
리액트는 body 태그 아래에 root 라는 id 를 가진 진입점에 가상 DOM 을 형성하고 실제로 모든 컴포넌트를 렌더링을 한다. Portal 은 새로운 진입점을 만들어서 부모 요소의 DOM 트리 구조와 별개의 위치에 컴포넌트를 렌더링하는 기능이다.
공식문서
Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공합니다.
Portal 을 사용해서 독립적인 위치에 컴포넌트를 렌더링하면
- 코드가 간결해져 유지보수성이 증가한다.
- 부모의 스타일에 영향받지 않아 스타일링 충돌을 피할 수 있다.
- 이벤트가 발생한 위치와 실제 이벤트가 처리되는 위치가 다르기 때문에 이벤트 버블링을 예방할 수 있다.
- 독립적인 컴포넌트로 상위 계층으로부터 영향받지 않아 성능을 최적화할 수 있다.
Portal 은 어떤 경우에 사용할까
모달 or 툴팁
대표적으로 모달 혹은 툴팁과 같은 팝업 요소 렌더링하는 경우에 사용한다.
모달은 사용자에게 어떤 작업을 진행하기 전 확인 요청, 추가 정보를 입력하도록 유도하는 경우 사용한다.
툴팁은 추가적인 정보를 제공하고, 기능에 대해 설명할 때 사용한다.
이런 요소들은 다른 요소 위에 나타나거나 특정 위치에 표시되어야 하기 때문에 Portal 을 이용하면 이를 세밀하게 제어할 수 있다.
Portal 사용법
기본 문법
Portal 을 생성하는 방법은 `createPortal()` 을 이용하면 된다. createPortal 을 호출하여 JSX 를 domNode 로 전달한다.
createPortal(children, domNode, key?)
- children : 사용하고자 하는 컴포넌트 혹은 문자열/숫자/배열 등 React 로 렌더링할 수 있는 요소들
- domNode : chidlren 을 렌더링할 위치(모달 진입점)
- key? : 선택 요소로 고유 문자열 혹은 번호
1. index.html 에 새로운 진입점 만들기
Portal 은 이미 존재하는 Node 에 렌더링이 가능하기 때문에 기존 진입점 외의 새로운 진입점을 생성해준다.
<!doctype html>
<html lang="en">
<head>
// ...
</head>
<body>
<div id="root"></div>
<div id="modal-portal"></div> // ✅ 새로운 진입점
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
2. createPortal( )
공식 문서에는 다음과 같이 사용하고 있다.
import { createPortal } from 'react-dom';
function MyComponent() {
return (
<div style={{ border: '2px solid black' }}>
<p>This child is placed in the parent div.</p>
{createPortal(
<p>This child is placed in the document body.</p>,
document.body
)}
</div>
);
}
위의 첫번째 p 태그는 root 안에 렌더링되고, 두 번째 createPortal 을 이용해 추가한 p 태그는 root 가 아닌 body 아래에 위치한다.
<body>
<div id="root">
...
<div style="border: 2px solid black">
<p>This child is placed inside the parent div.</p>
</div>
...
</div>
<p>This child is placed in the document body.</p>
</body>
하지만
컴포넌트에 직접 createPortal 을 사용하면 재사용이 불가능하기 때문에 재사용 가능한 portal 로 만들어보자.
// src/components/modal/modalPortal.tsx
import { ReactNode } from 'react'
import { createPortal } from 'react-dom'
const ModalPortal = ({ children }: { children: ReactNode }) => {
const modalRoot = document.getElementById('modal-portal') as HTMLElement
return createPortal(children, modalRoot)
}
3. 사용할 모달 컴포넌트 생성
// src/components/modal/Modal.tsx
const Modal = ({
close,
}: {
close: () => void
}) => {
return (
<Overlay onClick={close}>
<Container
onClick={e => e.stopPropagation()}
>
모달창입니다.
</Container>
</Overlay>
)
}
4. Portal 내부에 사용할 컴포넌트 감싸기
// src/page/Home.tsx
const Home = () => {
const [isOpen, setIsOpen] = useState(false);
const open = () => setIsOpen(true);
const close = () => setIsOpen(false);
return (
<Container>
<Button onClick={open}>
열기
</Button>
{isOpen && (
<ModalPortal>
<Modal close={close} />
</ModalPortal>
)}
</Container>
)
}
Portal 사용 전후 비교
사용 전
Portal 사용 전에는 모달 컴포넌트가 메인 DOM 트리의 `root` 에 위치
사용 후
Portal 사용 후 모달 컴포넌트가 메인 DOM 트리와는 별개의 개별적인 DOM Node인 `modal-portal` 에 위치
참고
'Core > React' 카테고리의 다른 글
[React] 컴포넌트 최적화를 위한 React.memo (28) | 2024.05.07 |
---|---|
[React] useModal Hook 여러 개의 모달 관리하기 (58) | 2024.05.02 |
[React] React-Router <NavLink> 컴포넌트 VS <Link> 컴포넌트 (61) | 2024.04.23 |
[React] Axios instance 와 interceptors 로 Axios 효율성 높이기 (41) | 2024.02.05 |
[React] React 에서 Axios 사용하기 (75) | 2024.02.04 |