์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- NVM
- git
- ํ๋ก์ ํธ
- CloudFront ๋ฌดํจํ
- ์ํฐ๋์ธํด์ญ
- toast err
- ํฅํด99
- ์ธํํ๊ทธ ์ํฐ
- ํ๊ณ ๋ก
- JS
- ๊ด๊ณ ์ง๊ตฌ
- react portal
- ์๋ณ์๋
- ์๊ณ ๋ฆฌ์ฆ
- JavaScript
- Redux
- Node
- CPU์ GPU์ ์ฐจ์ด์
- NextJs
- next/link
- Client-Side Navigation
- ์ํฐ๋ํ๋ฆฌ์จ๋ณด๋ฉ
- Til
- jsEvent Loop
- input error
- Mac OS NVM
- react
- Passed by Value
- ์ํฐํธ ํ๋ฆฌ์จ๋ณด๋ฉ์ธํด์ญ 1์ฃผ์ฐจ
- ์ ๋ น ์์กด์ฑ
- Today
- Total
SUIN
[React] ๋ ๋ฆฝ์ ์ธ DOM ๋ ธ๋๋ก ๋ ๋๋งํ๊ธฐ. with React Portal ๋ณธ๋ฌธ
[React] ๋ ๋ฆฝ์ ์ธ DOM ๋ ธ๋๋ก ๋ ๋๋งํ๊ธฐ. with React Portal
choi suin 2024. 6. 7. 16:50๐กํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๋ค ๋ณด๋ฉด ์๊ฐ๋ณด๋ค ๋ง์ ๊ณณ์์ ๋ชจ๋ฌ๊ณผ ํ์ ์ ๊ตฌํํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธด๋ค. React์์ ๋ชจ๋ฌ์ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ชจ๋ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ณ๋๋ก ๋ง๋ค์ด ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ๋ชจ๋ฌ ์ปดํฌ๋ํธ๋ฅผ ์ ์ธํด์ฃผ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๊ฒ ๋๋๋ฐ, ์ฐ๋ฆฌ๋ React์์ ์ ๊ณต๋๋ ๊ธฐ๋ฅ์ธ React Portal์ ์ถ๊ฐํ์ฌ ๋ชจ๋ฌ์ ๊ตฌํํด์ฃผ์๋ค.
React Portal์ ์์๋ณด๊ณ ์ฐ๋ฆฌ ํ๋ก์ ํธ์๋ ์ด๋ค ์์ผ๋ก Portal์ ์ถ๊ฐํ์ฌ ๊ตฌํํ๋์ง ์์๋ณด์.
React Portal๋?
React Portal์ React ์ ํ๋ฆฌ์ผ์ด์ ์์ DOM ์์๋ฅผ ๋ค๋ฅธ ์์น์ DOM ๋ ธ๋๋ก ๋ ๋๋งํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก React๋ ์ปดํฌ๋ํธ๋ฅผ ํด๋น ์ปดํฌ๋ํธ์ ๋ถ๋ชจ ์์ ๋ด์์ ๋ ๋๋ง ํ์ง๋ง ๋๋ก๋ ํน์ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ชจ ์์๊ฐ ์๋ ๋ค๋ฅธ ์์น๋ก ๋ ๋๋งํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ๋๋ฐ, ์ด๋ฐ ๊ฒฝ์ฐ์ React Portal์ ์ฌ์ฉํ๋ค.
ํฌํธ์ ์ฌ์ฉํ์ฌ ๋ ๋ฆฝ์ ์ธ UI ์์๋ฅผ ๋ ๋๋งํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ฌ, ๋๋กญ๋ค์ด ๋ฉ๋ด, ํดํ ๋ฑ๊ณผ ๊ฐ์ ๋ณด์กฐ์ ์ธ UI ์์๋ฅผ ๋ ๋๋งํ ๋ ์ฌ์ฉํ ์ ์๋ค.
https://ko.legacy.reactjs.org/docs/portals.html
https://react.dev/reference/react-dom/createPortal
โ ์ฐ๋ฆฌ๋ ์ Portal์ ์ฌ์ฉํ์ฌ ์ธ๋ถ์ ์กด์ฌํ๋ DOM ๋ ธ๋์ ๋ ๋๋ง ํ๋๋ก ๋ง๋ค์ด ์ฃผ์ด์ผ ํ๋๊ฑธ๊น?
React Portal ์ฌ์ฉ ์ด์
๋ฆฌ์กํธ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋๋ฉด ์์ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋๋ Tree ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์ด๋ฐ Tree ๊ตฌ์กฐ๋ ์ข ์ข ๋ถํธํจ์ ๊ฐ์ง๊ฒ ๋๋๋ฐ ๋ถ๋ชจ-์์ ๊ด๊ณ๋ฅผ ๊ฐ์ง๊ณ ์์ด DOM ๊ณ์ธต ๊ตฌ์กฐ์ ์ํฅ์ ๋ฏธ์น๊ฒ ๋๋ค. ํ์ง๋ง ๋ฆฌ์กํธ ํฌํ์ ์ฌ์ฉํ๋ฉด ๋ ๋ฆฝ์ ์ธ ์์น์์ ๋ ๋๋งํ๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
1. ๋ ๋ฆฝ์ ์ธ ์คํ์ผ ์ ์ฉ (CSS ์ถฉ๋ ๋ฐฉ์ง)
๋ถ๋ชจ ์ปดํฌ๋ํธ ์คํ์ผ์ ์ํฅ์ ๋ฐ๊ฑฐ๋ ์ค ์ ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ํ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค. ์ด๋ฐ ๊ฒฝ์ฐ Portal์ ์ฌ์ฉํ๋ฉด ๋ถ๋ชจ์ ์์ ๋ชจ๋ ์ธ๋ถ์ ์คํ์ผ๋ง ๊ท์น์ ์ํฅ์ ๋ฐ์ง ์๊ณ ๋ ๋ฆฝ์ ์ธ ์คํ์ผ๋ง์ ๊ฐ๋ฅํ๊ฒ ํด์ค๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ ์คํ์ผ ์ํฅ์ ๋ฐ๋ ์์
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div className="app">
<h1>Main Content</h1>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} />
</div>
);
};
/* App.css */
.app {
background-color: lightblue;
padding: 20px;
text-align: center;
/* ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์คํ์ผ ๊ท์น */
filter: blur(2px);
}
๋ชจ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ DOM ํธ๋ฆฌ์ ํฌํจ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์คํ์ผ์ธ filter: blur(2px)๊ฐ ๋ชจ๋ฌ์ ํจ๊ป ์ ์ฉ๋์ด ๋ชจ๋ฌ์ด ์ด๋ ธ์ ๋, ๋ชจ๋ฌ์ ๋ด์ฉ์ด ํ๋ฆฟํ๊ฒ ํ์๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
2. ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ์ ์ด
๋ฆฌ์กํธ ํธ๋ฆฌ ๊ตฌ์กฐ์ ๋ฐ๋ผ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์์๋ถํฐ ์ต์๋จ์ ๋ถ๋ชจ์์๋ฅผ ๋ง๋ ๋๊น์ง ์ด๋ฒคํธ๊ฐ ์ ํ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ๊ฐ ๋ณต์กํด์ง ์ ์๋ค. ์ด ๊ฒฝ์ฐ Portal์ ์ฌ์ฉํ๋ฉด ๋ด๋ถ์์ ๋ฐ์ํ ์ด๋ฒคํธ๋ Portal์ ์ฌ์ฉํ๋ ๋ถ๋ชจ ์์๊น์ง๋ง ๋ฒ๋ธ๋ง ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ๋ฅผ ๋์ฑ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
React Portal์ ์ฌ์ฉ ๋ฐฉ๋ฒ
๐๐ป ์ฐ๋ฆฌ ํ๋ก์ ํธ์์ ์ ์ฉํ ์ฝ๋๋ฅผ ๋ฐํ์ผ๋ก ์ด๋ป๊ฒ ํฌํธ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ฌ์ ๊ตฌํํ ์ ์๋์ง ์์๋ณด์!
1. ํฌํ์ ๋ํ DOM ์์ ์์ฑ- index.html
๋ค๋ฅธ DOM ์์์ ๋ํ id๋ฅผ ์ง์ ํ์ฌ ํด๋น ์์์ ํฌํ์ด ๋ ๋๋ง๋ ์ ์๋๋ก ์ง์
<!DOCTYPE html>
<html>
<head><title>app</title></head>
<body>
<h1>Welcome to my hybrid app</h1>
<div id="root"></div>
<div id="modal-root"></div> {/* ํฌํ์ด ๋ ๋๋ง๋ ์์น */}
</div>
</body>
</html>
2. Portal์ ๋ ๋๋งํ ์์น ์ ์ธ - ModalPortal.tsx
modal-root๋ผ๋ id๋ฅผ ๊ฐ์ง ์ธ๋ถ DOM ์์์ ๋ ๋๋งํ๊ธฐ ์ํด ModalPortal ์ปดํฌ๋ํธ ์ ์
const ModalPortal = ({ children }: TProps) => {
// ์ธ๋ถ DOM ์์์ ๋ ๋๋งํ ์์น๋ฅผ ์ง์
const el = document.getElementById('modal-root') as HTMLElement;
// createPortal ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ฌ์ ์ธ๋ถ DOM ์์์ ๋ ๋๋ง
return ReactDom.createPortal(children, el);
};
createPortal() ์ฌ์ฉ๋ฒ
ReactDom์ createPortal ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์ํ๋ ์ปดํฌ๋ํธ๋ฅผ Portal ์ํฌ ์ ์๋ค. child์ ๋ฃ์ด๋ ์ปดํฌ๋ํธ๋ ๋ ๋๋ง๋ ๋ ๊ฐ๊น์ด ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์๋ ์ฐ๋ฆฌ๊ฐ container์ ์ค์ ํด ๋ ์ปดํฌ๋ํธ์ ๋ ๋๋ง๋๋ค.
ReactDom.createPortal(child, container)
- child : ์๋ฆฌ๋จผํธ, ๋ฌธ์์ด, ํน์ fragment ๊ฐ์ ์ด๋ค ์ข ๋ฅ์ด๋ ๋ ๋๋ง ํ ์ ์๋ React์ ์์
- container : DOM ์๋ฆฌ๋จผํธ ์์
- ReactDom.createPortal(child, container)
3. Portal์ ์ฌ์ฉํ ์ ์ญ ์ปดํฌ๋ํธ ์์ฑ - GlobalModal.tsx
๋ชจ๋ฌ ๋ด๋ถ์ ์ฌ์ฉ๋๋ ๊ณตํต๋ ์คํ์ผ๋ง ๋ฐ์ค๋ ๋ฐฐ๊ฒฝ ๋ฑ์ UI ์์๋ฅผ GlobalModal ์ปดํฌ๋ํธ๋ฅผ ํตํด ์ฌ์ ์ ์ ์
export default function GlobalModal(props: IModal) {
return (
<ModalPortal>
<t.ModalContainer className="ModalContainer">
<t.ContentBox className="ContentBox">{props.children}</t.ContentBox>
<t.ModalBackdrop
className="ModalBackdrop"
onClick={(e: React.MouseEvent) => {
e.preventDefault();
props.onClose();
}}
></t.ModalBackdrop>
</t.ModalContainer>
</ModalPortal>
);
}
4. ๋ชจ๋ฌ์ด ๋ ๋๋ง ๋ ์์น ์ง์
const optionModal = isModalOpen && (
<GlobalModal onClose={() => setIsModalOpen(false)}>
<CartOptionModal onClose={() => setIsModalOpen(false)} />
</GlobalModal>
);
๊ฒฐ๊ณผ
์ฐธ๊ณ
https://velog.io/@enenaa/React-Portal-๊ธฐ์ ์-์ด์ฉํ์ฌ-Modal-๋ง๋ค๊ธฐ
'๊ฐ๋ฐ์ผ์ง' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ ์ ๊ถํ๋ณ ํ์ด์ง ์ ๊ทผ์ฒ๋ฆฌ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด๋ณด์ (0) | 2024.05.28 |
---|