
최근에 프로젝트를 진행하면서 React로 모달창을 구현하는 일을 하였기에, 이를 잊지 않으려고 끄적끄적 적게 되었다.
들어가기에 앞서, 모달창이 무엇인지에 대해 먼저 알아봐야겠다.
모달은 사용자가 특정 버튼이나 링크 등을 클릭했을 때 나오는 창으로, 이전 페이지 위에 새로운 레이어를 만들어 추가적인 정보나 문구르 보여줄 때 사용한다.
여기서 모달과 팝업(Pop-up)을 헷갈릴 수 있는데, 팝업은 현재 열려있는 페이지(브라우저)위에 또 다른 페이지를 띄우는 것을 말한다.
개인적인 생각으로는, 1번 페이지(브라우저)와 연관된 정보를 보여주는 것은 모달로, 개별의 정보를 제공할 때는 팝업을 사용하는 것이 좋다고 생각한다.
import React, { useState } from "react"
...
const [showEditOrDeleteModal, setShowEditOrDeleteModal] = useState(false);
...
<Button
onClick={() => setShowEditOrDeleteModal(!showEditOrDeleteModal)}
>
그룹 정보
</Button>
{showEditOrDeleteModal && (
<EditOrDeleteModal
showEditOrDeleteModal={showEditOrDeleteModal}
setShowEditOrDeleteModal={setShowEditOrDeleteModal}
groupId={id}
/>
)}
버튼을 클릭했을 때 set함수를 통해 모달을 띄울지 말지 결정하는 변수의 값을 변경한다.
이 boolean 변수를 통해 조건부렌더링을 하게 되는데, showEditOrDeleteModal 가 true이면, 기존에 만들어 주었던 EditOrDeleteModal 컴포넌트를 화면에 나타낸다.
현재 여기서는 조건부 렌더링을 결정하는 변수와 그 set함수를 props로 넘기고 있는데,
다시 생각해보니 set함수만 보내서 컴포넌트 내에서 false로 값만 설정해주면 될 것 같다.
화면 중앙에 띄울 모달 디자인을 해야 하는데, 다음은 전체 코드를 올려놓으려고 한다. 여기서 중요한 것은, position을 fixed나 absolute로 주어 고정시켜놓고, z-index를 설정하여 본문과 겹치지 않게 만들어야 한다는 것이다.
모달 컴포넌트
import React, { useState } from "react";
import * as S from "./style";
import DeleteCheckModal from "./DeleteCheckModal";
import EditListModal from "./EditListModal";
function EditOrDeleteModal({
showEditOrDeleteModal,
setShowEditOrDeleteModal,
groupId,
}) {
const [showDeleteCheckModal, setShowDeleteCheckModal] = useState(false);
const [showEditListModal, setShowEditListModal] = useState(false);
const handleButtonClick = () => {
setShowDeleteCheckModal(true);
};
return (
<S.ModalContainer>
<S.Exit
alt="exit"
onClick={() => setShowEditOrDeleteModal(!showEditOrDeleteModal)}
/>
<S.TextContainer>
<S.Text>
<S.ColorSpan>수정</S.ColorSpan> 또는 <S.ColorSpan>삭제</S.ColorSpan>
하실 수 있습니다.
</S.Text>
</S.TextContainer>
<S.ButtonContainer>
<S.Button onClick={handleButtonClick}>그룹 삭제</S.Button>
<S.Button onClick={() => setShowEditListModal(!showEditListModal)}>
명단 수정
</S.Button>
</S.ButtonContainer>
{showDeleteCheckModal && (
<DeleteCheckModal
setShowDeleteCheckModal={setShowDeleteCheckModal}
setShowEditOrDeleteModal={setShowEditOrDeleteModal}
groupId={groupId}
/>
)}
{showEditListModal && (
<EditListModal
showEditListModal={showEditListModal}
setShowEditListModal={setShowEditListModal}
groupId={groupId}
grade={grade}
classNum={classNum}
/>
)}
</S.ModalContainer>
);
}
export default EditOrDeleteModal;
style.js
import styled from "styled-components";
export const ModalContainer = styled.div`
width: 480px;
height: 288px;
flex-shrink: 0;
border-radius: 8px;
background: #fff;
box-shadow: 0px 0px 24px 0px rgba(38, 40, 43, 0.15);
position: fixed;
z-index: 1000;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
`;
export const Exit = styled.img.attrs({ src: exit })`
margin-top: 24px;
margin-right: 24px;
margin-left: 432px;
width: 24px;
`;
export const TextContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 9rem;
`;
export const Text = styled.p`
font-size: 20px;
font-weight: 700;
line-height: 32px;
`;
export const ColorSpan = styled.span`
color: #4849ff;
`;
export const ButtonContainer = styled.div`
display: flex;
width: 100%;
justify-content: space-around;
// 내부 폰트
color: #ffffff;
font-size: 20px;
font-weight: 700;
`;
export const Button = styled.button`
width: 192px;
height: 56px;
background-color: #4849ff;
`;

(그룹 정보 버튼 클릭)

구글링을 해보니 useRef를 통해서 모달 창 밖을 클릭했을 때 모달을 닫게 하는 기능도 있는 것 같다. 이건 다시 공부하여 기능을 추가한 뒤 새로 포스팅하도록 해야겠다.