📍
투두리스트 프로젝트를 진행하며 모달창을 만들어야 할 일이 있었는데 그때는 라이브러리를 사용하는게 좋을지 그냥 코드로 만들어 보는게 좋을지 고민하다가 일단 그냥 만들어보자! 라는 마음으로 만들었다.
이번에 다른 프로젝트를 진행하며 모달창을 만들일이 또 생겼는데 이번에는 chakra를 사용해 간단하게 모달창을 만들어 보았다.
라이브러리 없이 모달창 구현하기
1. 모달창 컴포넌트 생성 및 버튼 만들기
export default function TodoEditModal() {
return (
<>
<div className="edit-modal">
<button className="open-btn">
<span className="icon material-symbols-outlined">edit_square</span>
</button>
</div>
</>
);
}
- 모달 컴포넌트를 생성하고 클릭했을 때 모달창을 띄울 버튼을 만든다.
2. 버튼 상태 관리해주기
import React, { useState } from 'react';
export default function TodoEditModal() {
const [editModalOpen, setEditModalOpen] = useState(false);
const handleModal = () => {
setEditModalOpen(!editModalOpen);
};
return (
<>
<div className="edit-modal">
<button className="open-btn" onClick={handleModal}>
<span className="icon material-symbols-outlined">edit_square</span>
</button>
</div>
</>
);
}
- useState의 초기값을 불리언 값으로 설정해서 모달창의 열림 / 닫힘 여부 상태를 관리해준다.
- 버튼을 클릭하면 handleModal 함수를 호출해 현재 상태를 업데이트 해줄 수 있다. → ! 부정연산자를 사용해 클릭하면 현재 상태의 반대 값을 적용해준다.
3. 모달창 내용물 만들어주기
import React, { useState } from 'react';
import { useTodoStore } from '../store/useTodoStore';
export default function TodoEditModal({ todo }) {
const { onEdit } = useTodoStore();
const { id, done, title } = todo;
const [editModalOpen, setEditModalOpen] = useState(false);
const [text, setText] = useState();
const handleModal = () => {
setEditModalOpen(!editModalOpen);
};
const handleEditChange = e => {
setText(e.target.value);
};
const handleEdit = () => {
onEdit(id, done, text);
handleModal();
};
return (
<>
<div className="edit-modal">
<button className="open-btn" onClick={handleModal}>
<span className="icon material-symbols-outlined">edit_square</span>
</button>
</div>
{editModalOpen && (
<div
className="modal-container"
>
<div className="modal-content">
<div className="edit-date">
<p>
<span className="material-symbols-outlined">check</span>
{`생성일: ${editDate(todo.createdAt)}`}
</p>
<p>
<span className="material-symbols-outlined">edit</span>
{`수정일: ${editDate(todo.updatedAt)}`}
</p>
</div>
<textarea id={id} defaultValue={title} onChange={handleEditChange}></textarea>
<div className="edit-btn">
<button onClick={handleEdit}>저장</button>
<button onClick={handleModal}>닫기</button>
</div>
</div>
</div>
)}
</>
);
}
- 수정해야 할 todo 내용을 props으로 전달 받는다.
- 모달창을 열때는 논리연산자를 사용해 모달 상태가 true 일때만 모달창을 보여준다. (조건문 사용)
- 필요한 내용들을 채워주고 저장 버튼을 누르면 내용을 수정 함수에 전달하고 닫을 수 있는 함수를 호출한다.
- 닫기 버튼을 클릭하면 바로 모달창을 닫을 수 있는 함수를 호출한다.
4. 모달창 열기 및 배경 클릭했을 때 모달창 닫기
import React, { useRef, useState } from 'react';
import { useTodoStore } from '../store/useTodoStore';
export default function TodoEditModal({ todo }) {
const { onEdit } = useTodoStore();
const { id, done, title } = todo;
const [editModalOpen, setEditModalOpen] = useState(false);
const [text, setText] = useState();
const modalClose = useRef();
const handleModal = () => {
setEditModalOpen(!editModalOpen);
};
const handleEditChange = e => {
setText(e.target.value);
};
const handleEdit = () => {
onEdit(id, done, text);
handleModal();
};
const handleModalClose = e => {
if (e.target === modalClose.current) {
setEditModalOpen(false);
}
};
return (
<>
<div className="edit-modal">
<button className="open-btn" onClick={handleModal}>
<span className="icon material-symbols-outlined">edit_square</span>
</button>
</div>
{editModalOpen && (
<div
className="modal-container"
ref={modalClose}
onClick={handleModalClose}
>
<div className="modal-content">
<div className="edit-date">
...
</div>
<textarea id={id} defaultValue={title} onChange={handleEditChange}></textarea>
<div className="edit-btn">
<button onClick={handleEdit}>저장</button>
<button onClick={handleModal}>닫기</button>
</div>
</div>
</div>
)}
</>
);
}
- useRef를 변수에 담아 이벤트 처리에 사용한다.
- 닫기 버튼 뿐만아니라 배경이 되는 div를 클릭했을 때도 모달창이 닫힐 수 있게 함수를 호출한다.
Chakra UI 라이브러리로 모달창 구현하기
📌
Chakra UI - A simple, modular and accessible component library that gives you the building blocks you need to build your React a
Simple, Modular and Accessible UI Components for your React Applications. Built with Styled System
chakra-ui.com
💡 chakra UI란?
리액트 기반의 라이브러리로 사용자 인터페이스를 쉽게 구현할 수 있도록 다양한 컴포넌트와 유틸리티, 디자인 시스템을 제공한다.
Modal 컴포넌트 생성하기 및 모달창 구현하기
import {
Button,
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
SimpleGrid,
Textarea,
} from "@chakra-ui/react";
const EventRegistrationModal = ({...}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>일정 등록하기</ModalHeader>
<ModalBody>
...
</ModalBody>
<ModalFooter>
<Button
colorScheme="teal"
mr={3}
size="md"
onClick={onClose}
>
취소
</Button>
<Button colorScheme="teal" size="md" onClick={handleSaveEvent}>
저장
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
};
export default EventRegistrationModal;
- Modal: 자식요소를 감싸주는 래퍼 객체
- ModalOverlay: 모달창뒤의 검정 배경
- ModalContent: 모달창 안의 내용을 담는 컨테이너
- ModalHeader : 모달창 헤더
- ModalFooter: 모달창 푸터
- ModalBody: 모달창 내용
- ModalCloseButton: 모달창 닫기 버튼
const { isOpen, onOpen, onClose } = useDisclosure()
- chakra UI 에서 제공하는 훅을 통해 현재 상태여부, 열림, 닫힘 상태를 관리할 수 있다.
chakra UI는 공식문서가 잘되어있기때문에
더 자세한 내용은 공식문서를 보면서 사용하면 더 다양한 방법으로 사용할 수 있다.
✍🏼 결론
처음에는 라이브러리에 의존하기 보다는 직접 만드는 것이 좋지 않을까? 생각했는데 간단한 작업은 라이브러리를 활용하는것이 더 낫지 않을까 생각하고 있다.
모달창을 만들어 보지 않은 사람은 먼저 코드로 만들어보고 모달창 구조에 대해 생각해본 뒤에 간편하게 라이브러리를 사용해 보는것도 좋을것 같다. 무조건적으로 라이브러리에 의존하는건 좋지 않겠지만 적절하게 사용하는건 불필요한 코드를 줄이는데 도움을 주는것 같다!
'Front-end > React' 카테고리의 다른 글
[React] 리액트쿼리(React Query)란? (0) | 2024.03.25 |
---|---|
[React] react Swiper로 슬라이드 기능 구현하기 - 버튼 커스텀, breakpoints (0) | 2024.03.20 |
[React] Redux Middleware는 어떤 용도로 사용될까? (0) | 2024.01.18 |
[React] 상태관리 라이브러리 - zustand (0) | 2024.01.17 |
[React] 상태관리 라이브러리 - Redux (0) | 2024.01.16 |