리액트 타이머
목적
- 메세지 전송버튼
- 5분 타이머 만들기
- 재전송 버튼 클릭 시 다시 Reset
- localstorage 사용하여 횟수 저장
- 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> {/* 리셋 횟수 표시 */}
)
문제해결 완료