[React] react-modal에 애니메이션 효과 추가하기

앤지·2022년 12월 15일
0
post-thumbnail

react-modal package를 사용하여 만든 모달에 ✨이쁘게✨애니메이션을 추가해보자

예전 모달

나는 여기서 스르륵 나타나고 스르륵 사라지는 효과를 넣어보고 싶었다.

react-modal 을 커스텀 해보자

기존에 정적으로 스타일을 넣어준것과 반대로 모달창의 상태에 따라 스타일이 변화해야했기 때문에 프로젝트에서 사용하고 있는 styled-component를 이용하여 구현하고 싶었다.

modal창과 overlay 모두 커스텀을 할 수 있는 방법을 찾아보았고 react-modal이 contentElment와 overlayElement props를 제공한다는것을 발견하였다.

저 div 태그를 이용한다면 내가 원하는것을 구현할 수 있다고 생각하였고 바로 styled-component를 이용하여 코드를 작성하였다.

const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`;

const fadeOut = keyframes`
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
`;

const ModalStyle = styled.div`
  animation: ${(prop: { isOpen: boolean }) => (prop.isOpen ? fadeIn : fadeOut)}
    0.2s ease-in;
    visibility: ${(prop: { isOpen: boolean }) =>
      prop.isOpen ? "visible" : "hidden"}
    transition: visibility 0.2s ease-out;
  
`;

const OverlayStyle = styled.div`
  animation: ${(prop: { isOpen: boolean }) => (prop.isOpen ? fadeIn : fadeOut)}
    0.2s ease-in;
  visibility: ${(prop: { isOpen: boolean }) =>
    prop.isOpen ? "visible" : "hidden"};
  transition: visibility 0.2s ease-out;
`;

그 결과

나타나는건 이쁘게 잘 나타나는데 없어질때 원하는 애니메이션 기능이 구현되지 않았다.

사라지는 애니메이션 구현하기

나름대로 고민한 결과 애니메이션이 보여지기 전에 모달창의 display속성이 변화하기 때문에 내가 원하는것이 구현이 안된거라는 결론을 냈다.

그렇다면 모달창이 닫히는 시간을 조금 지연시킨다면 원하는 애니메이션을 구현할 수 있지 않을까?

setTimeout함수를 써보자

부모컴포넌트에서 받아오는 open상태와 별개로 모달창 내에서 제어하는 visible이라는 상태를 하나 더 만들었다.

그리고 닫힘버튼이 눌리는순간 toggleModal함수를 바로 호출하는것이 아닌 우선 visible상태를 바꾸어 애니메이션 효과를 보여준다음에 호출하는것으로 로직을 작성하였다.

  // 컴포넌트가 사라지는 시점을 지연시키기 위한 상태
  const [visible, setVisible] = useState<boolean>(false);
 
 // 부모컴포넌트에서 받아온 open상태가 변화할때 visible상태 바꿔주기 
  useEffect(() => {
    setVisible(isOpen);
  }, [isOpen]);
  
 
  const handleCloseBtnClick=()=>{
   // visible의 상태를 false로 바꿔줌과 동시에 애니메이션 동작 
  	 setVisible(false);
  // 애니메이션이 끝나면 toggleModal함수 실행으로 모달창 닫기 
     setTimeout(() => {
           toggleModal();
      }, 200);
  }
  

  <Modal
      isOpen={isOpen}
      style={customStyles}
      contentElement={(props, children) => (
        <ModalStyle isOpen={visible} {...props}>
          {children}
        </ModalStyle>
      )}
      overlayElement={(props, contentElement) => (
        <OverlayStyle isOpen={visible} {...props}>
          {contentElement}
        </OverlayStyle>
      )}
    >

0개의 댓글