[React] Zustand로 전역 모달 관리하기
■ 지금까지의 모달 관리 방법
■ zustand 전역 모달 관리 방법
안녕하세요.
이전 포스팅까지 zustand에 대해 알아보는 시간을 가졌습니다.
이번에는 zustand를 이용한 전역 모달을 관리하는 방법에 대해 포스팅 해볼겁니다 !
■ 지금까지의 모달 관리 방법 - 로컬 on, off 방식
이전까지는 모달을 사용하는 각 컴포넌트 안에서
- 모달 컴포넌트를 import
- useState로 모달 상태를 관리
- 조건부를 사용한 모달창 띄우기
로 단순하고 직관적인 방법을 사용해왔습니다.
import { useState } from 'react';
import LoginModal from './LoginModal';
function Header() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>로그인</button>
{isOpen && <LoginModal onClose={() => setIsOpen(false)} />}
</>
);
}
이 방식을 사용할 경우
모달을 사용하는 컴포넌트마다 import Modal from '...' 구문을 작성해야하니
모달 수가 많을 수록 중복 코드가 늘어남을 알 수 있습니다.
뿐만 아니라 각 컴포넌트마다 별도의 useState를 사용하니
일관성이 떨어지고 예상치 못한 버그가 생길 수 있다는 문제가 있었습니다.
이렇게한 이유는 제가 생각할 수 있는 최선이었던 것 같습니다.
리액트를 시작한지 2개월이 됐는데, 다른 방법이 있다곤 생각을 못해본 것 같습니다. 🥵
최근에 기술 면접을 봤는데, 이 부분에 대해 질문해주시더군요.
" 왜 이런 방식을 사용했는지???" 🤥
전 당당하게
" 어 .. ? 이렇게 관리하는거 아닌가요 ㅋㅋㅋ ㅠㅠㅠ "
라고 말했습니다.
ㅎㅎ 면접은 망했지만~
다른 방법에 대해 고민해볼 수 있는 기회를 얻어답니다.
■ zustand로 전역 모달 관리 방법
zustand를 도입해서 모달을 하나의 전역 store에서 관리하면 어떨까요 ?
그리고, App.js 같이 최상위 컴포넌트 한곳에서만 모달을 렌더링하는 겁니다.
이렇게 하면 코드 중복도 줄이고 일관성도 생기겠죠!!
예시 코드를 한번 볼까요 ~
modalStore.js
store에선 현재 모달 상태와 열기, 닫기에 대한 상태변경을 관리합니다.
import { create } from 'zustand';
export const useModalStore = create((set) => ({
currentModal: null, // 'login' or 'signup'
openModal: (modal) => set({ currentModal: modal }),
closeModal: () => set({ currentModal: null }),
}));
App.js
조건부에 맞게 모달을 렌더링해줍니다.
import React from 'react';
import { useModalStore } from './modalStore';
import LoginModal from './modals/LoginModal';
import SignupModal from './modals/SignupModal';
import HomePage from './HomePage';
function App() {
const { currentModal, closeModal } = useModalStore();
return (
<>
<HomePage />
{currentModal === 'login' && <LoginModal onClose={closeModal} />}
{currentModal === 'signup' && <SignupModal onClose={closeModal} />}
</>
);
}
export default App;
이전 방식은 모달이 필요한 컴포넌트마다 이 작업을 해주었죠 ? ( 중복코드 와르르 )
HomePage.js
모달을 띄우고 싶은 컴포넌트에선 간단하게 모달 상태만 바꿔주면 됩니다.
import React from 'react';
import { useModalStore } from './modalStore';
function HomePage() {
const openModal = useModalStore((state) => state.openModal);
return (
<div>
<h1>홈페이지</h1>
<button onClick={() => openModal('login')}>로그인</button>
<button onClick={() => openModal('signup')}>회원가입</button>
</div>
);
}
export default HomePage;
LoginModal.js
import React from 'react';
function LoginModal({ onClose }) {
return (
<div style={modalStyle}>
<h2>로그인 모달</h2>
<button onClick={onClose}>닫기</button>
</div>
);
}
const modalStyle = {
position: 'fixed',
top: '30%',
left: '50%',
transform: 'translateX(-50%)',
padding: '20px',
background: 'white',
border: '1px solid #ccc',
zIndex: 1000,
};
export default LoginModal;
zustand로 모달을 관리할 때의 장점은
1. 전역에서 상태를 쉽게 제어할 수 있다.
2. 불필요한 prop drilling 제거 가능하다.
3. 일관된 상태 관리가 가능하다.
4. 필요한 모달만 렌더링하니 성능이 최적화된다.
5. 컴포넌트가 독립적이라 유지보수가 쉽다.
이번 포스팅은 여기까지입니다.
저는 이 방식으로 코드 리팩토링하러 가겠습니다.. 총총 ㅋㅋ 😂