React Timer 만들기

TigerStoneV·2024년 10월 22일
0
post-thumbnail

리액트 타이머

목적

  1. 메세지 전송버튼
  2. 5분 타이머 만들기
  3. 재전송 버튼 클릭 시 다시 Reset
  4. localstorage 사용하여 횟수 저장
  5. 5회가 되면 Alert 띄우기

작업

// CountdownTimerProps  

import React, { useEffect } from "react";

interface CountdownTimerProps {
  seconds: number;
  isActive: boolean;
  onComplete: () => void;
  onTick: (seconds: number) => void;
}

const CountdownTimer: React.FC<CountdownTimerProps> = ({
  seconds,
  isActive,
  onComplete,
  onTick,
}) => {
  useEffect(() => {
    let interval: NodeJS.Timeout | null = null;

    if (isActive && seconds > 0) {
      interval = setInterval(() => {
        onTick(seconds - 1); // 부모 컴포넌트에 seconds 감소 요청
      }, 1000);
    }

    return () => {
      if (interval) clearInterval(interval); // 컴포넌트 언마운트 시 인터벌 클리어
    };
  }, [isActive, seconds, onTick]);

  useEffect(() => {
    // seconds가 0일 때 onComplete 호출
    if (seconds === 0) {
      onComplete();
    }
  }, [seconds, onComplete]);

  // MM:SS 형식으로 변환하는 함수
  const formatTime = (totalSeconds: number) => {
    const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, "0");
    const secs = String(totalSeconds % 60).padStart(2, "0");
    return `${minutes}:${secs}`; // "MM:SS" 형식으로 반환
  };

  return <h1>{formatTime(seconds)}</h1>; // 현재 타이머 상태 출력
};

export default CountdownTimer;
//App
import CountdownTimer from "@/core/components/Timer";
 // 타이머
  const initialSeconds = 10; // 5분을 초로 변환
  const [seconds, setSeconds] = useState(initialSeconds); // 총 초 수
  const [isActive, setIsActive] = useState(false); // 타이머 상태

  const handleStart = () => {
    setIsActive(true);
  };

  const handlePause = () => {
    setIsActive(false);
  };

  const handleReset = () => {
    setIsActive(false);
    setSeconds(initialSeconds); // 타이머를 5분으로 리셋
  };

  const handleTick = (newSeconds: number) => {
    setSeconds(newSeconds); // 부모 컴포넌트에서 초 수 변경
  };

  const handleComplete = () => {
    setIsActive(false); // 타이머가 끝나면 멈춤
    alert("타이머가 완료되었습니다!"); // 완료 알림
  };
  
  return (
	 <CountdownTimer
            seconds={seconds}
            isActive={isActive}
            onComplete={handleComplete}
            onTick={handleTick}
          />
)

문제

  • 해당 코드로 작업을 진행하면 start reset등등 작업이 정상적으로 되지만
    문제가 5분이 다되어서 00:01초에 한번 00:00초에 한번 총 두번 Complete Alert 가 발생하는것을 알 수 있다

문제해결

 useEffect(() => {
    if (phone) {
      setPhoneStatus(true);
    }
  }, [phone]);
  const handleChangeAuthValue = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    // 숫자만 입력되도록 필터링
    if (/^\d*$/.test(value)) {
      setAuthValue(value);
    }
  };
  // 타이머
  const initialSeconds = 10; // 5분을 초로 변환
  const [seconds, setSeconds] = useState(initialSeconds); // 총 초 수
  const [isActive, setIsActive] = useState(false); // 타이머 상태
  const [isCompleted, setIsCompleted] = useState(false);
  const handleStart = () => {
    setIsActive(true);
    setIsCompleted(false);
  };

  const handlePause = () => {
    setIsActive(false);
  };

  const handleReset = () => {
    setIsActive(false);
    setSeconds(initialSeconds); // 타이머를 5분으로 리셋
    setIsCompleted(false);
  };

  const handleTick = (newSeconds: number) => {
    if (newSeconds >= 0) {
      // seconds가 0 이하가 되지 않도록
      setSeconds(newSeconds); // 부모 컴포넌트에서 초 수 변경
    }
  };

  const handleComplete = () => {
    if (!isCompleted) {
      // 완료 상태가 false일 때만 호출
      setIsCompleted(true); // 완료 상태 업데이트
      alert("타이머가 완료되었습니다!"); // 완료 알림
    }
    setIsActive(false); // 타이머가 끝나면 멈춤
  };
  • imCompleted 라는 상태 state를 하나 더 만들어서 동작시킴

이제 LocalStorage에 저장

 const [resetCount, setResetCount] = useState(0); // 리셋 횟수
 
  // localStorage에서 리셋 횟수 불러오기
  useEffect(() => {
    const storedCount = localStorage.getItem("resetCount");
    if (storedCount) {
      setResetCount(Number(storedCount));
    }
  }, []);
    // 리셋 횟수를 localStorage에 저장
    useEffect(() => {
    localStorage.setItem("resetCount", String(resetCount));
  }, [resetCount]);
  const handleStart = () => {
    setIsActive(true);
    setIsCompleted(false);
  };

  const handlePause = () => {
    setIsActive(false);
  };

  const handleReset = () => {
     setIsActive(false);
    setSeconds(initialSeconds); // 타이머를 5분으로 리셋
    setIsCompleted(false);
    setResetCount((prevCount) => {
      const newCount = prevCount + 1;
      // 5번 리셋할 때 알림 표시
      if (newCount === 5) {
        alert("리셋 버튼을 5번 눌렀습니다!");
      }
      return newCount;
    });
  };

  const handleTick = (newSeconds: number) => {
    if (newSeconds >= 0) {
      // seconds가 0 이하가 되지 않도록
      setSeconds(newSeconds); // 부모 컴포넌트에서 초 수 변경
    }
  };

  const handleComplete = () => {
    if (!isCompleted) {
      // 완료 상태가 false일 때만 호출
      setIsCompleted(true); // 완료 상태 업데이트
      alert("타이머가 완료되었습니다!"); // 완료 알림
    }
    setIsActive(false); // 타이머가 끝나면 멈춤
    
    
    return (
        <button onClick={isActive ? handlePause : handleStart}>
            {isActive ? "Pause" : "Start"} {/* 시작/정지 버튼 */}
          </button>
          <button onClick={handleReset}>Reset</button> {/* 리셋 버튼 */}
          <p>리셋 횟수: {resetCount}</p> {/* 리셋 횟수 표시 */}
)

문제해결 완료

profile
개발 삽질하는 돌호랑이
post-custom-banner

0개의 댓글