일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
- 웹디실기
- 웹디자인기능사실기
- 자바스크립트
- 웹디자인기능사
- PROJECT
- web
- git
- github
- CSS
- 연산자
- 비전공자
- HTML
- 프론트엔드
- 정보처리기사
- react
- 세로메뉴바
- 리액트
- 깃
- 코딩독학
- 슬라이드전환
- 렛츠기릿자바스크립트
- Supabase
- 코드공유
- JavaScript
- 웹퍼블리셔
- 실기
- JS
- jQuery
- 생활코딩
- 타입스크립트
- Today
- Total
코딩하는라민
[React] useModal Hook 여러 개의 모달 관리하기 본문
[React] useModal Hook 여러 개의 모달 관리하기
useModal Hook 이란?
`useModal` hook 은 React 에서 모달을 간편하게 관리하기 위한 방법이다.
useModal hook 을 통해 열기, 닫기 상태와 같은 모달과 관련된 로직을 모듈화해서 재사용할 수 있다.
왜 커스텀 훅을 만들어서 사용할까?
모달을 사용할 때 모달을 열고 닫기 위해 `isOpen` 라는 state 를 사용한다.
하지만 여러 페이지에서 모달을 사용할 경우 각 컴포넌트마다 isOpen 을 매번 선언해줘야한다.
import { useState } from "react"
import LoginModal from "@/components/modalsLoginModal"
const Home = () => {
const [isOpen, setIsOpen] = useState(false)
const openModal = () => setIsOpen(true)
const closeModal = () => setIsOpen(false)
return (
<>
<button onClick={openModal}>로그인</button>
{isOpen && (
<LoginModal closeModal={closeModal} />
)}
</>
)
}
하지만 `useModal` 을 사용하면 컴포넌트마다 isOpen 을 선언해줄 필요가 없어진다.
따라서 모달을 사용하는 과정을 단순화하고 모달 로직을 `재사용 가능`한 형태로 추상화하여 코드의 가독성과 유지보수성을 향상시킬 수 있다.
하지만 모달 로직이 단순하거나 재사용률이 떨어진다면 직접 구현하는 편이 더 간편할 수 있다.
하지만 useModal 사용으로 인해 코드의 재사용성이 증가하고, 모달 관련 로직을 관리하기 편하다.
useModal Hook 사용방법
useModal Hook 기본 형태
useModal 에 모달을 열고 닫기 위한 openModal 함수, CloseModal 함수와 모달 컴포넌트르를 조건부 렌더링하기 위한 isOpen 을 정의해주면 된다.
import { useState } from 'react'
const useModal = () => {
const [isOpen, setIsOpen] = useState(false)
const openModal = () => setIsOpen(true)
const closeModal = () => setIsOpen(false)
return {
isOpen,
openModal,
closeModal
};
};
사용하기
import useModal from '@/components/modal/useModal.ts'
const Components = () => {
const { isOpen, openModal, closeModal } = useModal();
return (
<div>
<button onClick={openModal}>열기</button>
{isOpen && (
<div>
<div>모달입니다.</div>
<button onClick={closeModal}>닫기</button>
</div>
)}
</div>
);
};
하지만 이러한 형태는 한 컴포넌트 내에서 다른 여러 모달을 열 경우 사용이 불가능하다.
useModal hook 을 한 컴포넌트 내에서 여러 개의 모달을 다룰 수 있게 커스텀해보자.
여러 개의 모달을 관리하는 useModal hook
여러 모달을 관리하는 modals state 를 생성해준다. modals 의 타입은 key 가 string 타입이고 value 가 boolean 인 객체 형태이다.
모달을 열고 닫을 때마다 modals 을 업데이트 해주는데, 기존의 값에서 새로운 값만 업데이트하는 형식이다. 이 때, open, close 함수의 매개변수로 key 값으로 모달의 이름을 string 형태로 넣어주면 된다.
import { useState } from 'react'
interface Modals {
[key: string]: boolean
}
const useModal = () => {
const [modals, setModals] = useState<Modals>({})
const openModal = (key: string) => {
setModals(prev => ({
...prev,
[key]: true
}))
}
const closeModal = (key: string) => {
setModals(prev => ({
...prev,
[key]: false
}))
}
const isOpen = (key: string) => modals[key]
return {
isOpen,
openModal,
closeModal
}
}
export default useModal
사용하기
기존에는 isOpen 을 state 의 형태로 open, close 함수에서 값을 업데이트 했으나, modals 의 key 값에 맞는 모달 상태를 가져와 사용할 모달 컴포넌트를 조건부 렌더링해주면 된다.
사용 방법은 위의 경우와 거의 유사하다.
import useModal from '@/hook/useModal'
import CategoryModal from '@/components/modals/CategoryModal'
import LoginModal from '@/components/modals/LoginModal'
const Home = () => {
const { isOpen, openModal, closeModal } = useModal()
return (
<>
{
isOpen('카테고리') && (
<CategoryModal closeModal={closeModal} />
)
}
<button onClick={openModal('카테고리')}>카테고리 열기</button>
{
isOpen('로그인') && (
<LoginModal closeModal={closeModal} />
)
}
<button onClick={openModal('로그인')}>로그인</button>
</>
)
}
실행하고자 하는 모달 컴포넌트에 closeModal 을 props 로 내려주고, 모달 컴포넌트에서 closeModal 을 실행하면 된다.
// CategoryModal.tsx
const CategoryModal = ({
closeModal
}: {
closeModal: (key: string) => void
}) => {
...
return (
<ModalLayout closeModal={() => closeModal('카테고리')}>
<Container>
...
</Container>
</ModalLayout>
)
}
// ModalLayout.tsx
const ModalLayout = ({
children,
closeModal,
}: {
children: ReactNode
closeModal: () => void
}) => {
return (
<Overlay onClick={() => closeModal()}>
<Container
onClick={e => e.stopPropagation()}
>
{children}
</Container>
</Overlay>
)
}
'Core > React' 카테고리의 다른 글
[React] 컴포넌트 최적화를 위한 React.memo (28) | 2024.05.07 |
---|---|
[React] React Portal 사용하기 (58) | 2024.04.30 |
[React] React-Router <NavLink> 컴포넌트 VS <Link> 컴포넌트 (61) | 2024.04.23 |
[React] Axios instance 와 interceptors 로 Axios 효율성 높이기 (41) | 2024.02.05 |
[React] React 에서 Axios 사용하기 (75) | 2024.02.04 |