front-mockup(3)Modal

Creating the dots·2021년 11월 9일
1

project-2-느린우체통

목록 보기
3/10

기간
2021/11/4 ~ 2021/11/9

메일작성 페이지

<CKEditor />
<Select />
<Datepicker />
Styled Component
Node-schedule || cron
<Modal />

구현화면

메일작성 페이지에서 전송하기 버튼을 눌렀을때, ConfirmModal 컴포넌트가 화면 중앙에 나타나고, 모달창 바깥 또는 모달창의 닫기 버튼을 눌렀을때, 모달창이 꺼지도록 구현해보려고 한다.

모달창이 띄워질 상위컴포넌트에 상태 만들기

  • <Buttons />의 <전송하기> 버튼을 눌렀을때 상태를 변경하기 위해 props로 전달하고, <ConfirmModal />도 배경과 <닫기> 버튼을 눌렀을때 상태를 변경하기 위해 props로 함수(closeModal)를 전달한다.

  • 따라서 하위 컴포넌트에서 버튼을 클릭했을때 상위 컴포넌트의 상태를 변경할 수 있다.

function Mailform() {
  //Buttons에서 <전송하기> 버튼 눌렀을때 상태변경해서 모달창 띄우기
  const [isModalOpen, setIsModalOpen] = useState(false);
  const closeModal = () => {
    setIsModalOpen(!isModalOpen);
  };

  return (
    <>
      <div className="Mailform-wrapper">
        <Mailinfo />
        <Editor />
        <Buttons closeModal={closeModal} />
        {isModalOpen && <ConfirmModal closeModal={closeModal} />}
      </div>
    </>
  );
}
export default Mailform;

모달창 띄웠을때 css

  • 전체 화면에 반투명 회색 배경을 띄우기 위해 width와 height를 꽉 채워 사용한다.
  • position을 fixed로 하여, 왼쪽 상단 모서리를 고정시킨다.
  • 모달창의 내용이 들어가는 .modal-box는 position을 absolute로 하고, transform, translate를 사용해 해당 div의 크기로 틀어진 가운데 중심을 맞추어준다.
  • 여기서 modal-box.confirmModal-container의 자식요소이므로, 위쪽에 위치시키기 위해 z-index를 사용한다.
.confirmModal-container {
  width: 100%;
  height: 100vh;
  border: 1px solid black;
  background-color: rgba(0, 0, 0, 0.4);
  z-index: 10;
  position: fixed;
  top: 0;
  left: 0;
}
.confirmModal-container .modal-box {
  width: 300px;
  height: 200px;
  background-color: white;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 100;
}

모달창 배경과 취소 버튼을 눌렀을때 모달창 끄기

문제상황

이 부분은 이해하기 어려운 부분 중 하나였다. z-index를 사용했기 때문에, 모달창을 눌렀을때에는 모달창이 닫히면 안된다고 생각했다. 다시말해, 회색 배경 또는 모달창의 취소버튼을 눌렀을때만 모달창이 닫히도록 하고 싶었고, 모달창은 눌러도 닫히면 안됐다. 그런데, 모달창을 눌렀을때도 창이 닫혔다.

원인

원인은 z-index는 같은 레벨의 요소들 간에만 적용된다는 점에 있었다.자식요소에 z-index를 준다고 해도 부모 요소 위에 있는 것이 아니라는 뜻이다. 자식요소의 z-index를 아무리 높여도 부모 밖으로는 나갈 수 없다. 부모요소 안에 있는 자식요소 부분을 클릭하더라도 모달창이 닫힌 것이다.

해결

event.target과 event.currentTarget을 활용해 문제를 해결할 수 있었다. 회색배경을 클릭했을때는 handleclose 함수를 동작시켜 e.target === e.currentTarget인 경우에만 closeModal 함수를 동작시킨다. 그리고, 취소 버튼을 클릭했을때에는 바로 closeModal 함수를 동작시킨다.

다음을 보면, 차례로 두개씩 모달창을 눌렀을때, 회색배경을 눌렀을때, 취소버튼을 눌렀을때 e.targete.currentTarget이다.

즉, 모달창을 눌렀을때에는 e.target은 모달창이지만 e.currentTarget은 회색박스로 일치하지 않으므로 모달창이 닫히지 않고, 회색배경을 눌렀을때는 이 두개가 일치하므로 모달창이 닫힌다. (css에 적용했던 z-index는 지워도 된다.)

function ConfirmModal({ closeModal }) {
  const handleClose = (e) => {
    console.log(e.target);
    console.log(e.currentTarget);
    if (e.target === e.currentTarget) {
      closeModal();
    }
  };
  return (
    <>
      <div className="confirmModal-container" onClick={handleClose}>
        <div className="modal-box">
          <p>
            예약이 완료된 편지는 전송취소가 불가합니다. 편지를 보내시겠습니까?
          </p>
          <button className="btn-close" onClick={closeModal}>
            취소
          </button>
          <button className="btn-close" onClick={}>
            보내기
          </button>
        </div>
      </div>
    </>
  );
}
profile
어제보다 나은 오늘을 만드는 중

0개의 댓글