패스트캠퍼스 데브캠프 67~68일차 [React, Zustand]

Su Min·2024년 8월 27일
0
post-thumbnail

모달 상태 전역으로 관리하기 ( 모달: 로그인 모달, 회원가입 모달 )

useModalStore.ts

useModalStore는 zustand의 create를 사용하여 초기값인 modals와 state를 변경할 openModal, closeModal 메서드를 작성해주었다.
각 메서드는 modalName을 받아 해당 모달의 상태를 업데이트한다.

import { create } from 'zustand';

interface IModals {
  modalName: string;
  modalState: boolean;
}

interface State {
  modals: IModals;
}

interface Actions {
  openModal: (modalName: string) => void;
  closeModal: (modalName: string) => void;
}

const useModalStore = create<State & Actions>((set) => ({
  modals: {
    modalName: '',
    modalState: false,
  },
  openModal: (modalName) =>
    set(() => ({
      modals: {
        modalName,
        modalState: true,
      },
    })),
  closeModal: (modalName) =>
    set((state) =>
      state.modals.modalName === modalName
        ? {
            modals: {
              modalName: '',
              modalState: false,
            },
          }
        : state,
    ),
}));

export default useModalStore;

Signin.tsx

signin컴포넌트에서 signup컴포넌트를 열어 모달UI를 바로 변경해 줄 수도 있다.

import Modal from '@/components/Modal'
import useSignModalStore from '@/stores/useModalStore'

const Signin: React.FC = () => {
  const signinModal = useModalStore((state) => state.modals)
  const openSigninModal = useModalStore((state) => state.openModal)
  const closeSigninModal = useModalStore((state) => state.closeModal)

  const onLogin = () => {
    closeSigninModal('signin') 
  }
  
  const children: React.ReactNode = (
    <>
      <h2 css={{ margin: '40px 0 20px', fontSize: '28px' }}>Login</h2>
      <form css={{ width: '330px' }} onSubmit={(e) => onLogin(e)}>
        .
      	.
        .
        <div>
          <button css={submitBtn} type="submit">
            Login
          </button>
        </div>
      </form>
      <p css={{ fontSize: '14px', marginBottom: '40px' }}>
        계정이 없으신가요?
        <button onClick={() => {openSigninModal('signup')}}>
          Sign Up now
        </button>
      </p>
    </>
  );
  return (
    <>
      {signinModal.modalName === 'signin' && signinModal.modalState ? (
        <Modal children={children} modalName="signin" />
      ) : null}
    </>
  );
};

export default Signin;

Signup.tsx

import Modal from '@/components/Modal';
import useModalStore from '@/stores/useModalStore';

const Signup: React.FC = () => {
  const signupModal = useModalStore((state) => state.modals);
  const openSigninModal = useModalStore((state) => state.openModal);

  .
  .
  .
  
  const children: React.ReactNode = (
    <>
      <h2 css={{ margin: '50px 0 20px', fontSize: '28px' }}>회원가입</h2>
      <form css={{ width: '330px' }} onSubmit={(e) => onSignup(e)}>
       .
       .
       .
        <button css={submitBtn} type="submit">
          가입하기
        </button>
      </form>
      <p css={{ fontSize: '14px', marginBottom: '40px' }}>
        로그인하시겠습니까?
        <button css={modalMovementBtn} onClick={() => openSigninModal('signin')}>
          Go back to login
        </button>
      </p>
    </>
  );
  return (
    <>
      {signupModal.modalName === 'signup' && signinModal.modalState ? (
        <Modal children={children} modalName="signup" />
      ) : null}
    </>
  );
};

export default Signup;

Modal.tsx

공용 Modal컴포넌트는 모달 내용과 모달 이름을 props로 받아 X를 누르면 해당 모달을 닫도록 한다.

import useModalStore from '@/stores/useModalStore';

interface SignModalProps {
  children: React.ReactNode;
  modalName: string;
}

const Modal = ({ children, modalName }: SignModalProps) => {
  const closeSomeModal = useModalStore((state) => state.closeModal);

  return (
    <div css={wrapper}>
      <div css={modalArea}>
        <button css={closeBtn} onClick={() => closeSomeModal(modalName)}>
          <X />
        </button>
        {children}
      </div>
    </div>
  );
};

export default Modal;
profile
성장하는 과정에서 성취감을 통해 희열을 느낍니다⚡️

0개의 댓글

관련 채용 정보