본문 바로가기
프로그래밍/JS & React

JS & React 정리(3) - 간단 모달창 만들기, 알림받기 설정

by 코로디링 2023. 9. 17.

 

이번 정리 내용은 모달 컴포넌트 구현!! 그리고 이를 활용해 알림받기 설정하기!

 

먼저 구현 화면부터 보면

주황색 알림받기 버튼을 누르게 되면 아래 보이는 것처럼 모달 창이 뜨고 관심고객수가 1증가하도록 구현해 놓았다.

(당연히 UI상에서만 보여지는 거고 실제로 반영되는건 1도 없음 ㅎㅎ)

대표사진 삭제

메인 페이지 알림받기 배너

 
사진 삭제

알림 설정 클릭 시 모달창

 

 

1. 클릭 시 숫자 1 증가시키기

  • 사실 이건 정리하기도 민망하게 간단하지만.. 그래도 이번 프로젝트를 하면서 알게 된 점이 있어 적어보려고 함.
  • 인터넷 강의를 듣다가 알게 된 내용인데 useState를 사용해서 값을 변화시킬 때 저렇게 이전 값을 가져와서 함수로 구현해야 한다고 함.
  • setCount((count) => count +=1)); (O) setCount(count + 1); (X)
import { useState } from "react";
import Modal from "../common/Modal";
import styles from "../../css/main/main.module.css";

const NoticeBanner = () => {
  const [count, setCount] = useState(5200);
  const [isModalOpen, setIsModalOpen] = useState(false);

  const openModal = () => {
    setIsModalOpen(true);
    setCount((count) => (count += 1));
  };

  return (
    <div className={styles.notice_banner}>
      <p>DanDog 공식 스토어</p>
      <span className={styles.interested_ppl}>관심고객수 {count}명</span>
      <span className={styles.notification} onClick={openModal}>
        {isModalOpen && (
          <Modal
            isModalOpen={isModalOpen}
            setIsModalOpen={setIsModalOpen}
            modalContent={"알림 설정이 완료되었습니다."}
          />
        )}
        알림받기
      </span>
    </div>
  );
};

export default NoticeBanner;
 

 

 

2. 모달 창 구현하기

import styles from "../../css/common/modal.module.css";

import PropTypes from "prop-types";
import { useNavigate } from "react-router-dom";

const Modal = ({
  isModalOpen,
  setIsModalOpen,
  modalContent,
  modalAfterPath,
}) => {
  const navigate = useNavigate();

  if (!isModalOpen) return null;
  const closeModal = () => {
    setIsModalOpen(false);
    navigate(modalAfterPath);
  };

  return (
    <div className={styles.modal} onClick={closeModal}>
      <div className={styles.modal_wrap} onClick={(e) => e.stopPropagation()}>
        <p className={styles.modal_content}>{modalContent}</p>
        <span className={styles.modal_btn} onClick={closeModal}>
          확인
        </span>
      </div>
    </div>
  );
}; // Modal

// 모달을 사용하게 위해 props로 전달해 주어야 하는 것.
Modal.propTypes = {
  isModalOpen: PropTypes.bool.isRequired,
  setIsModalOpen: PropTypes.func.isRequired,
  modalContent: PropTypes.string.isRequired,
  modalAfterPath: PropTypes.string,
};

export default Modal;
 

(1) 아주 간단하게 모달을 구현하기 위해 CSS 속성만 사용해 모달 창을 만들어 줌.

    • 모달 배경에 fixed를 주고 width, height를 100%로 준 뒤 백그라운드를 연하게 줌.
    • 그리고 그 위에 모달창 박스를 띄워 내용을 담도록 구성함.
    • 모달창 CSS는 하단에 첨부

 

(2) 모달을 정상적으로 오픈하기 위해서는 모달을 사용하는 상위 컴포넌트에서 정해진 값들을 보내주어야 함.

    • useState로 정의한 모달 오픈 여부의 boolean값 변수(isModalOpen), boolean값을 바꿔주는 함수(setIdModalOpen), 모달 내용(modalContent), 모달 닫힘 후 이동 경로(modalAfterPath) 이렇게 네 가지의 속성을 props로 보내주어야 함.
// 모달을 사용하게 위해 props로 전달해 주어야 하는 것.
Modal.propTypes = {
  isModalOpen: PropTypes.bool.isRequired,
  setIsModalOpen: PropTypes.func.isRequired,
  modalContent: PropTypes.string.isRequired,
  modalAfterPath: PropTypes.string,
};
 
    • 위에 보이는 것처럼 전해주어야 할 것들을 propTypes로 정의해 놓음. (모달 닫힘 후 이동 경로는 필수 아님.)

 

(3) 전해진 값들을 모달 컴포넌트와 함수에 적절히 넣어주기

    • isModalOpen이 false일 경우 아무것도 반환하지 않음 (근데 어차피 false이면 상위 컴포넌트에서 열리지 않을텐데 뭐하러 이중으로 저걸 해놨을까...ㅋㅋㅋㅋ 이렇게 쓸데없는 코드가 늘어나는거구나.. )
    • 암튼 뭐.. 모달창이 열렸을 경우 props로 받아온 내용을 modalContent에 넣어줌.
    • 그리고 확인 버튼이나 바깥의 창을 눌렀을 경우 closeModal 함수 실행
      • 모달 창 상태를 false로 바꿔주고 setIsModalOpen(false);
      • useNavigate 훅을 사용해 원하는 경로로 이동 navigate(modalAfterPath);

 

(4) 참고로 useState와 openModal 함수는 상위 컴포넌트에 정의함!

    • isModalOpen && <Modal />을 활용하여 isModalOpen이 true일 때 모달이 열리도록 함.
/* 모달 창 CSS  */
.modal {
  text-align: center;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  /* 반투명한 배경 */
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2;
}

.modal_wrap {
  width: 40%;
  height: 30%;
  background-color: white;
  padding: 20px;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
  display: grid;
  grid-template-rows: 2fr 1fr;
}

.modal_content {
  color: #000;
  font-size: 1.3em;
  align-self: center;
}

.modal_btn {
  width: 100px;
  height: 50px;
  line-height: 50px;
  background-color: #ffe344;
  border-radius: 10px;
  box-shadow: 0 2px 5px rgb(0, 0, 0, 0.1);
  justify-self: center;
}
 

정리 및 느낀 점

  • 모달창을 여러 컴포넌트에서 쓸 수 있도록 구성한 건 맞지만 아주 간단한 형식의 모달이라 나중에 보완해야할 듯 하다....
  • 선택형, 글쓰기형, 복잡한 내용이 있는 형식 등등 다양한 형식이 있기 때문에 차차 구현하려 함!!
  • 그리고 CSS로만 구성했는데.. 나중에 백엔드랑 연동할 때는 왠지 다른 방식으로 고쳐야 할 듯 함... ㅠ