-
[React] 모달 바깥 부분 클릭시 모달 꺼지게 하기React 2022. 4. 12. 23:29
저는 다양한 프로젝트를 하며 모달 기능을 구현해보았는데요. 모달 기능을 구현하면서 모달 바깥쪽을 클릭 시 모달이 꺼지게 하는 기능을 구현해야 하는 상황이 생길 때가 많았습니다. 처음에 이 기능을 구현할 때 어려움을 겪었던 것이 생각나 한 번 글로써 다시 정리해보려 합니다!
이번화는 다음 스택을 사용하였습니다.
- Next.js
- Typescript
- Styled-Component
- Recoil
아래의 코드들은 저의 한 프로젝트에서 복사해온 코드입니다.
일단 Recoil을 사용하여 전역 변수를 선언을 해주었습니다.
export const isOpen = atom<boolean>({ key: "isOpen", default: false, }); export const isWriteModalOpen = atom<boolean>({ key: "isWriteModalOpen", default: false, });
그리고 버튼을 클릭 시 모달이 나오게끔 모달 컴포넌트를 만들어보겠습니다.
WriteModal.tsx
import React from "react"; import { useRecoilState } from "recoil"; import { isWriteModalOpen } from "../../../atoms/index"; import Input from "../../Input/Modal/Input"; import * as s from "./Style"; import TextInput from "../../Input/TextInput/TextInput"; import ModalButton from "../../Button/ModalButton/ModalButton"; const people = [ "선택", "1명", "2명", "3명", "4명", "5명", "6명", "7명", "8명", "10명", "11명", "12명", "13명", "14명", "15명", "16명", "17명", "18명", "19명", "20명", ]; type modal = { visible: boolean; }; interface ModalProps { modalObj: modal; } const WriteModal: React.FC<ModalProps> = ({ modalObj }) => { const [writemodalIsClose, setWriteModalIsClose] = useRecoilState(isWriteModalOpen); function onClose() { setWriteModalIsClose(false); } return ( <> {!writemodalIsClose ? null : ( <> <s.ModalOverlay visible={modalObj.visible} onClick={onClose} /> <s.ModalWrapper visible={modalObj.visible}> <Input type="text" /> <s.Dropdown> <p>인원수</p> <s.DropdownSelect> {people.map((people, idx) => ( <s.DropdownOption key={idx}>{people}</s.DropdownOption> ))} </s.DropdownSelect> </s.Dropdown> <TextInput /> <s.ButtonWrapper> <ModalButton text="취소" btnType={"cancel"} onClick={onClose} /> <ModalButton text="땡겨!!" btnType={"pull"} onClick={onClose} /> </s.ButtonWrapper> </s.ModalWrapper> </> )} </> ); }; export default WriteModal;
Style.ts
import styled from "styled-components"; import Config from "../../../Constants/Config.json"; type StyleProps = { visible?: boolean; mode?: string; }; export const ModalOverlay = styled.div<StyleProps>` display: ${(props) => (props.visible ? "block" : "none")}; z-index: 999; position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: ${Config.COLOR.SUPERLIGHTGRAY}; opacity: 0.4; `; export const ModalWrapper = styled.div<StyleProps>` width: 45%; height: 80%; display: ${(props) => (props.visible ? "block" : "none")}; z-index: 1000; position: fixed; top: 10%; left: 28%; box-sizing: border-box; display: flex; flex-direction: column; padding: 2rem; background-color: ${({ theme }) => theme.background}; border-radius: 10px; `; export const Dropdown = styled.div` display: flex; margin-top: 1.3vh; position: relative; p { font-size: 18px; font-weight: bold; color: #989898; } &:hover + .lists { opacity: 1; visibility: visible; } `; export const DropdownSelect = styled.select` display: flex; justify-content: center; align-items: center; margin-top: -0.1vh; margin-left: 0.5%; width: 10%; height: 2rem; border-radius: 3px; background-color: ${Config.COLOR.BLUE}; color: ${Config.COLOR.WHITE}; font-size: 18px; font-weight: bold; .icon { cursor: pointer; } `; export const DropdownOption = styled.option` padding: 1rem; margin-left: 2vh; color: ${Config.COLOR.WHITE}; font-size: 18px; font-weight: bold; `; export const ButtonWrapper = styled.div` width: 100%; height: 6%; margin-left: 65.3%; margin-top: -4vh; `;
코드 설명
1. WriteModal.tsx라는 모달 컴포넌트를 하나를 만들고 그 안에 ModalOverlay 스타일을 이용하여 visible 값을 관리해줘요.
(여기서 값을 관리할 때 visible type을 선언해주고 Style.ts에서 StyleProps로 visible props 값을 가져와 아래의 코드처럼 값을 비교해줘요)type StyleProps = { visible?: boolean; }; export const ModalOverlay = styled.div<StyleProps>` display: ${(props) => (props.visible ? "block" : "none")}; z-index: 999; position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: ${Config.COLOR.SUPERLIGHTGRAY}; opacity: 0.4; `;
2. 해당 ModalOverlay로 모달 바깥 부분의 부분을 지정해줘요. 그리고 ModalOverlay, ModalWrapper에 visible 값을 넣어줍니다.
<s.ModalOverlay visible={modalObj.visible} onClick={onClose} /> <s.ModalWrapper visible={modalObj.visible}>
3. ModalOverlay에 onClick 함수를 선언해주어 바깥쪽을 클릭 시 모달이 꺼지게끔 하는 함수를 선언해줍니다. 여기서 전역 변수를 사용하여 값을 관리해줍니다.
const [writemodalIsClose, setWriteModalIsClose] = useRecoilState(isWriteModalOpen); function onClose() { setWriteModalIsClose(false); }
마무리
이런식으로 StyleProps와 useRecoilState를 사용하여 모달 바깥쪽 클릭 시 꺼지게끔 하는 기능을 구현해보았는데요.
코드를 수정할 부분이나 피드백을 주시면 감사히 받겠습니다 😎'React' 카테고리의 다른 글
[React] SWR이 뭘까? (0) 2022.08.27 [React] Github Action으로 Typescript + React 프로젝트 CI/CD 구축하기 (with S3, CloudFront) (1) 2022.08.23 [React] Recoil과 Redux의 차이점 (0) 2022.06.06