본문 바로가기

1일1티스토리

250909 - React 인증번호 타이머 구현

오늘까지 탈퇴 끝냈으면 좋겠다고 해서 하루종일 개발만 했다..

타이머는 5분, 이메일 번호 전송 이후부터 타이머가 작동되게 하면 된다.

 

const [timer, setTimer] = useState(0) // 처음에는 0으로 시작

const handleSendEmail = async () => {
    setIsLoading(true);
    try {
      await deleteRequest();
      setIsEmailSent(true);
      setTimer(300); // 5분 타이머 시작
      console.log('인증번호 전송 완료');
    } catch (error) {
      console.error('인증번호 전송 실패:', error);
    } finally {
      setIsLoading(false);
    }
  }
  
const formatTime = () => {
    const minutes = Math.floor(timer / 60)
    const seconds = timer % 60
    return `${minutes}:${seconds < 10 ? `0${seconds}` : seconds}`
}

useEffect(() => {
    let interval: NodeJS.Timeout;
    if (!isVerified && timer > 0) {
        interval = setInterval(() => {
            setTimer((prevTimer) => {
                if (prevTimer <= 1) {
                    clearInterval(interval);
                    setIsVerified(false);
                    setVerificationCode('');
                    setIsEmailSent(false);
                    setHasError(false);
                    return 0;
                }
                return prevTimer - 1;
            });
        }, 1000);
    }

    return () => clearInterval(interval);
}, [isVerified, timer]);

 

이메일 전송을 누르자마자, 타이머의 시간이 300초 (5분) 로 설정된다.

 

formatTime 함수는 " 남은 분 : 남은 초 " 순서로 화면에 남은 시간을 띄운다.

 

setInterval(() => { ... }, 1000);

{ ... } 안에 있는 함수는 1000밀리초 = 1초마다 실행된다.

1초마다 콜백함수를 실행하며 타이머 값을 줄이니, 0이 되면 자동 정지 및 상태 초기화가 진행된다.

 

<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
  <div className={styles.inputWrapper}>
    <input
      type="text"
      className={`${styles.emailInput} ${hasError ? styles.error : ''}`}
      placeholder={t('withdraw.step2.verificationPlaceholder')}
      value={verificationCode}
      onChange={(e) => {
        setVerificationCode(e.target.value);
        if (hasError) setHasError(false); // 입력 시 에러 상태 해제
      }}
      disabled={isVerified}
    />
    <span className={styles.timer}>{formatTime()}</span>
  </div>
  {hasError && (
    <div className={styles.errorMessage}>
      {t('withdraw.step2.error')}
    </div>
  )}
</div>

{formatTime()} 을 통해 변경되는 시간을 출력한다.