개발 프로젝트/스위트케어

alert를 모달 알림창으로 변경하기

티시즌 2024. 1. 29. 22:02

ESLint 설정 탓에 alert를 쓸 때마다 no-alert 에러가 발생했다.

에러를 없애기 위해, 사용자 지정 모달 알림창으로 변경을 시도했다.

다음 사항을 고려했다.

1. 애니메이션
아래에서 위로 슬라이딩되며 나오고, 위에서 아래로 슬라이딩되며 사라지기를 원했다.
이를 위해 컴포넌트가 생기고 일정 시간이 지나면 active 클래스가 on/off되게 했다.
opacity와 transform으로 효과를 주고, transition으로 연속적인 애니메이션이 되도록 했다.

.Alert {
/**중략**/
  position: fixed;
  top: 75%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: all 0.5s ease-in-out;
}

.active {
  opacity: 1;
  transform: translate(-50%, -65%);
}

 

2. 시간
기본 3초 동안 지속되게 했다.
그런데 alert 창이 떠 있는 중 input 입력을 하면 입력이 지속되는 동안에는 창이 꺼지지 않는 문제가 있었다.
이것은 입력을 지속하면서 useEffect가 계속해서 새로운 setTimeout을 생성하기 때문에 발생하는데, useEffect의 종속성 배열에 값을 추가해 놓아서 그런 거였다. 종속성 배열을 비우면 마운트될 때에만 실행되므로 setTimeout이 리셋되지 않는다.
다만, 다른 알림은 바로 표시되어야 하므로 message를 대신 추가했다.

import React, { useEffect, useState } from 'react';

import styles from './Alert.module.css';

const Alert = ({ message, duration, closeAlert }) => {
  const [isActive, setIsActive] = useState(false);

  const animationTime = 500; // ms

  useEffect(() => {
    setTimeout(setIsActive(true), animationTime);
    const timeoutObj = setTimeout(() => {
      setIsActive(false);
      setTimeout(closeAlert, duration * 1000 - animationTime * 2);
    }, duration * 1000);

    return () => clearTimeout(timeoutObj);
  }, [message]);

  return <div className={`${styles.Alert} ${isActive ? styles.active : ''}`}>{message}</div>;
};

export default Alert;


더불어, 타임스탬프를 Alert 컴포넌트의 key로 지정해서 버튼을 계속 누르면 알림창이 새로 렌더링되도록 했다.