티스토리 뷰

모달 스토어

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();
      },
    );
  };

 

급하게만들다보니 좀... 이건 아닌 거 같다는 생각이 많이 든다 나중에 개선해서 다시 만들어보도록 하자

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
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
글 보관함