모달 상태 전역으로 관리하기 ( 모달: 로그인 모달, 회원가입 모달 )
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컴포넌트에서 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;
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컴포넌트는 모달 내용과 모달 이름을 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;