티스토리 뷰
모달 스토어
import { create } from "zustand";
type ModalStore = {
isModal: boolean; // 모달의 열림/닫힘 상태
text: string; // 모달에 표시할 텍스트
confirmButtonText: string; // 확인 버튼에 표시할 텍스트
cancelButtonText: string; // 취소 버튼에 표시할 텍스트 (선택 사항)
path?: string; // (선택 사항) 모달과 관련된 경로
isConfirm: boolean; // 확인이 필요한 경우(버튼 2개일 때)
onConfirmCallback?: () => void; // 초기화
openModal: (
text: string,
confirmButtonText: string,
cancelButtonText: string,
isConfirm?: boolean,
path?: string,
onConfirmCallback?: () => void,
) => void; // 모달 열기 함수
closeModal: () => void; // 모달 닫기 함수
};
export const useModalStore = create<ModalStore>((set) => ({
isModal: false,
text: "",
confirmButtonText: "",
cancelButtonText: "",
isConfirm: false,
path: "",
onConfirmCallback: undefined, // 초기화
openModal: (
text,
confirmButtonText,
cancelButtonText = "",
isConfirm = false,
path = "",
onConfirmCallback,
) =>
set({
isModal: true,
text,
confirmButtonText,
cancelButtonText,
isConfirm,
path,
onConfirmCallback,
}), // 모달 열기
closeModal: () =>
set({
isModal: false,
text: "",
confirmButtonText: "",
cancelButtonText: "",
path: "",
onConfirmCallback: undefined,
}), // 모달 닫기
}));
타타님이 모달 라이브러리를 사용하지 말고 전역으로 만들어서 사용하라셔서 만든 전역 모달
급하게 만들긴했는데 매개변수가 너무 많다...
전역상태에서 사용하기 위해 쥬스탄드를 이용했다
모달 컴포넌트
"use client";
import { useModalStore } from "@/store/modalStore";
import { Typography } from "@mui/material";
import { useRouter } from "next/navigation";
const Modal = () => {
const {
isModal,
text,
cancelButtonText,
confirmButtonText,
path,
isConfirm,
closeModal,
onConfirmCallback,
} = useModalStore((state) => ({
isModal: state.isModal,
text: state.text,
cancelButtonText: state.cancelButtonText,
confirmButtonText: state.confirmButtonText,
path: state.path,
isConfirm: state.isConfirm,
closeModal: state.closeModal,
onConfirmCallback: state.onConfirmCallback,
}));
const router = useRouter();
const onModalHandler = () => {
closeModal(); // 모달 닫기
if (onConfirmCallback) {
onConfirmCallback(); // 확인 콜백 호출
}
if (path) {
router.push(path); // 경로로 이동
}
};
if (!isModal) return null; // 모달이 열려 있지 않으면 아무것도 렌더링하지 않음
return (
<div className="fixed inset-0 flex items-center justify-center">
{/* 자식이 영향 받지 않기 위해 부모 분리 */}
<div className="fixed inset-0 bg-primary opacity-[80%]" />
{/* 메인 div 박스 */}
<div
className={
"z-10 flex h-[138px] w-[342px] flex-col items-center justify-center rounded-lg bg-white py-6"
}
>
<Typography variant="body1">{text}</Typography>
<div
className={`${isConfirm && "flex w-full justify-center gap-[10px]"}`}
>
{isConfirm && (
<button
onClick={() => closeModal()}
className="mt-6 h-[52px] w-[152px] rounded-lg border border-gray3 bg-white text-primary"
>
<Typography variant="title4" className="px-[18px] py-[11px]">
{cancelButtonText}
</Typography>
</button>
)}
<button
onClick={onModalHandler}
className={`mt-6 rounded-lg bg-primary text-white ${isConfirm ? "h-[52px] w-[152px]" : "h-[44px] w-[66px]"}`}
>
<Typography variant="title4" className="px-[18px] py-[11px]">
{confirmButtonText}
</Typography>
</button>
</div>
</div>
</div>
);
};
export default Modal;
사용 예시
const onResetHandler = () => {
openModal(
"정말로 초기화 하시겠습니까?",
"초기화하기",
"취소하기",
true,
"",
() => {
// 초기화
reset();
},
);
};
급하게만들다보니 좀... 이건 아닌 거 같다는 생각이 많이 든다 나중에 개선해서 다시 만들어보도록 하자