현제 브라우저 위에 새로운 레이어를 렌더하는 창
💡 또다른 브라우저 페이지를 띄우는 팝업창과 다른 개념
❌ 기존 컴포넌트 안에 생성하는 방법은 간단하고 쉽지만 재사용성에 대한 제한점이 있다
✅ React Portal을 활용하여 재사용성을 고려한 모달창 생성
React.DOM.createPortal(child, container)
import { useEffect, useRef, useState, FC, ReactNode } from "react";
import { createPortal } from "react-dom";
import styled from "styled-components";
type ReactNode =
| ReactChild
| ReactFragment
| ReactPortal
| boolean
| null
| undefined;
interface IProps {
children: ReactNode;
}
children
컴포넌트 타입 지정
ReactNode
: 리액트 타입스크립트용 @type
const ModalPortal: FC<IProps> = ({ children }) => {
const ref = useRef<Element | null>();
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
if (document) {
const dom = document.querySelector("#root-modal");
ref.current = dom;
}
}, []);
if (ref.current && mounted) {
return createPortal(
<Container>
<div className="modal-background" />
{children}
</Container>,
ref.current
);
}
return null;
};
export default ModalPortal;
Header.tsx
:
...
return(
<Container>
...
{modalOpened && (
<ModalPortal>
<SignUpModal />
</ModalPortal>
)}
</Container>
);
};
export default Header;
useRef
hook을 사용하여 _app.tsx
의 DOM bind
useEffect
: 모달이 렌더 되었을 때 setMounted(true)
children
: 자식 컴포넌트를 받는 Props 규칙
✅ 자식 컴포넌트의 따라 재사용이 가능한 ModalPortal
생성 완료!