Just Do IT!

리액트 custom hook으로 모달창 구현하기 (useModal) 본문

개발 공부/React

리액트 custom hook으로 모달창 구현하기 (useModal)

MOON달 2023. 10. 2. 18:53
728x90

사이드 프로젝트를 하면서, 본격적으로 custom hook을 써보기로 했다. (나혼자 결정한거임)

아직 UI 구현 단계지만, 이렇게 페이지가 많은 프로젝트를 한 적도 처음이고 플로우 차트를 통해 페이지를 파악하는 것도 처음이다! 그래서 재밌기는 하지만, 시작하기 전에 구조를 생각해야 하는 시간이 좀 길어졌다.

 

캠프에서는 그냥저냥 구조 그려보고 그대로 기능 구현해봤는데, 사이드 프로젝트는 다르다.

일단 디자이너님이 그려주신 화면을 구현하기 위해서 필요한 단계들을 생각해보고, 피그마를 꼼꼼히 보고 있다.

 

아무튼!

그래서 반복되는 컴포넌트들은 따로 custom hook을 이용해서 만들어보기로 하고 가장 첫 번째로 모달창을 구현했다.

 

 

 

 

 

 

 

 

custom hook?

https://react.vlpt.us/basic/21-custom-hook.html

 

21. 커스텀 Hooks 만들기 · GitBook

21. 커스텀 Hooks 만들기 이번에 사용 될 코드는 다음 CodeSandbox 에서 확인 할 수 있습니다. 컴포넌트를 만들다보면, 반복되는 로직이 자주 발생합니다. 예를 들어서 input 을 관리하는 코드는 관리 할

react.vlpt.us

벨로퍼트님의 gitbook을 보면 자세히 나와 있다.

반복되는 로직을 효율적으로 줄이기 위해서 직접 hook을 만드는 것이다.

useState, useMemo 등 use[ ] 라는 형식으로 파일을 만들어 사용하면 된다.

hook 폴더 > useModal.js  요런 형식으로 이루어져 있다.

 

 

 

 

 

 

 

useModal.js 만들기
import { useState } from "react";
import styled from "styled-components";

export default function useModal() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  // modal open
  const openModal = () => {
    setIsModalOpen(true);
    document.body.style.overflow = "hidden";
  };

  // modal close
  const closeModal = () => {
    setIsModalOpen(false);
    document.body.style.overflow = "unset";
  };

  // modal component
  const Modal = ({ children, style }) => {
    return isModalOpen ? (
      <Container>
        <Background onClick={closeModal} />
        <ModalBlock onClick={(e) => e.stopPropagation()} style={style}>
          <Close onClick={closeModal}>x</Close>
          <Contents>{children}</Contents>
        </ModalBlock>
      </Container>
    ) : null;
  };

스타일까지 포함하면 길어질것 같아서 자체 생략.

위의 코드가 내가 프로젝트에 사용한 useModal.js 파일이다.

 

모달창에서 필요하다고 생각되는 건 모달 열기, 닫기 가 있다. 그리고 모달이 열렸는지 닫혔는지 여부까지.

 

useState를 사용해 isModalOpen (모달이 열렸는지) 상태 관리를 해주고 false인 경우에는 아무것도 열리지 않는다.

opemModal() 함수는 모달을 여는 함수,

closeModal() 함수는 모달을 닫는 함수이다.

 

그리고

document.body.style.overflow = "hidden";
document.body.style.overflow = "unset";

이 두 코드는 모달창이 열렸을 때, 뒤의 웹페이지의 스크롤 여부를 위해 추가한 코드이다.

모달이 열렸을 때는 스크롤이 되지 못하도록 하는 코드이다.

 

이런 식으로 useModal.js 파일을 생성하면, 이제 다른 컴포넌트에서 바로 불러와서 모달을 사용할 수 있다.

 

 

 

 

 

 

 

사용 예시 

이제 모달창을 구현할 때 custom hook을 사용할 차례.

 

import useModal from "../../hooks/useModal";
import styled from "styled-components";
import OutIcon from "../../assets/Btn_out.png";

export default function OutStudy() {
  // useModal 사용해서 그룹방 탈퇴 모달 구현
  const { isModalOpen, openModal, closeModal, Modal } = useModal();

  // open modal
  const handleModal = () => {
    openModal();
  };

  // 탈퇴 시 탈퇴 완료 후, 나의 그룹 스터디방 목록에서 제거 기능 구현 필요

  return (
    <>
      <Icon onClick={handleModal} src={OutIcon} alt="outstudy" />

      {/* modal */}
      <Modal style={{ width: "400px", height: "220px" }}>
        <ModalContent>
          <div>
            <ModalBody>해당 스터디방을 탈퇴하시겠습니까?</ModalBody>
          </div>
          <Button>탈퇴하기</Button>
        </ModalContent>
      </Modal>
    </>
  );
}

 

기능 구현은 아직 안해서....ㅋㅋㅋㅋ

위의 코드를 보면 useState를 사용할 때처럼 코드를 구현하면 된다.

지금 생각해보니 isOpen, closeModal은 사용 안해도 되는데 괜히 썼다. 나중에 수정해야지.

 

아무튼.

useModal custom hook에서 불러오느 기능들을 그냥 사용하면 된다.

 

모달을 열 버튼에 onClick 이벤트를 추가하고 modal 코드를 적어주면 끝.

내가 Modal 창 width와 height를 지정해주지 않아서 저렇게 각 모달창 마다 style을 따로 주고 있다.

 

위의 코드는 그룹방 탈퇴 모달창인데, 디자이너님이 정해주신 크기가 있어서 그걸 사용하고 있다.

그리고 ModalContent 안에 필요한 문장과 버튼 등을 넣으면 끝.

 

짠!

내가 구현한 그룹방 탈퇴 모달창은 이런 모습이다. 내가 뒤의 부분을 블러 처리 형식으로 스타일을 넣어서 어느 모달창이나 이런 형식으로 나오고 있다.

 

 

 

 

 

 

 

 


처음에 custom hook에 대해 배웠을 때는 이걸 내가 어떻게 쓸 수 있지? 하면서 좀 걱정했는데 시간은 좀 걸렸어도 잘 이해한 것 같다. 이렇게 큰 규모의 프로젝트는 처음이기도 하고. (물론 내 기준에서 큰 규모임)

 

여튼, 모달창 말고도 pagination을 custom hook으로 만들었는데 그것도 블로그에 정리해봐야겠다.