리액트 모달 관리 방법에 대해 정리한 글입니다.
const App= () =>{
const [isModal,setIsModal] = useState(false);
return isModal ? <Component /> : null;
}
<Modal onClose={()=>setIsShow(false)} />
const [isShow,setIsShow] = useState(false);
const [isShow1,setIsShow1] = useState(false);
const [isShow2,setIsShow2] = useState(false);
interface modalState {
isOpen:boolean,
onCloseCallback:Function,
onActionCallback:Function,
}
const Modal = () =>{
const modal:modalState = useSelector(state => state.modal);
return modal.isOpen ? <ModalComponent {...modal} /> : null;
}
const App = () => {
return (
<Router />
<Components...>
<Modal />
</Router>)
}
직렬화
되지 않는 데이터를 넣기에 기본 원칙에 위배됨(함수)
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
const useModal = ({ Modal }: { Modal: any }) => {
const ref = useRef<Element | null>();
const [isShow, setIsShow] = useState(false);
useEffect(() => {
const dom = document.getElementById('root-modal');
ref.current = dom; // ref에 dom 값 전달
}, []);
return {
isShow,
modalOpen: () => setIsShow(true),
modalClose: () => setIsShow(false),
ModalView: () => {
if (ref.current == null || !isShow) {
return null;
}
return createPortal(<Modal />, ref.current);
},
};
};
export default useModal;
const App= () => {
const {
isShow,
modalOpen,
modalClose,
ModalView: Portal,
} = useModal({
Modal: QRModal, <-- 원하는 모달을 넣어줄 수 있음
});
return (
<Routes>
<...Components />
<ModalView /> <-- 출력부
</Routes>
)
}
createPortal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링 하는 방법중 하나 입니다!
저는 개인적으로 마지막 방식을 선호해서 프로젝트에 바로 적용 했습니다.
모달을 여러개 띄워야 되는 상황 + 디버깅이 쉬운 상황을 고려해야 되기에 마지막 방식에 맞지 않나 싶습니다.
여러 프로젝트를 하며 모달을 어떻게 하면 효율적으로 관리할까? 이런 고민을 통해 나온 방식들 입니다. 정답은 없지만 그 상황에 맞는 방식은 존재하기에 프로젝트 상황과 모달에 요구사항에 대해 고민해보시고 방법을 고려하시는게 제일 좋은것 같습니다.
위 방식 말고도 좋은 방식이 있으면 언제든 댓글로 알려주세요! 읽어주셔서 감사합니다.