반응형
Next.js 에서 React와 TypeScript를 이용해서 타이머를 구현해보도록 하겠습니다.
React Hook은 useEffect와 useMemo를 사용하였습니다.
1. 컴포넌트 렌더링 시 setInterval 함수를 통해서 1초 감소
2. setInterval 종료
3. 다시 재렌더링
이런 메커니즘으로 타이머가 진행 됩니다.
1분 이하에는 0.1초 단위로 시간이 내려갑니다.
See the Pen React + TypeScript Starter by powerku (@powerku) on CodePen.
타이머 컴포넌트
timer.tsx
const Timer = ({minute = 15, second = 0}: TimerProps) => {
const [min, setMinute] = React.useState(1)
const [sec, setSecond] = React.useState(2)
const [milliSec, setMilliSec] = React.useState(0)
const [isRunning, setIsRunning] = React.useState(false);
const [minuteSecondMode, setIsMinuteSecondMode] = React.useState(true);
const formatMinute = React.useMemo(() => {
return min.toString().padStart(2, '0')
}, [min])
const formatSecond = React.useMemo(() => {
return sec.toString().padStart(2, '0')
}, [sec])
React.useEffect(() => {
if (min === 0) {
setIsMinuteSecondMode(false);
}
}, [min]);
React.useEffect(() => {
if (!isRunning) {
return;
}
let interval;
if (minuteSecondMode) {
interval = setInterval(() => {
if (sec > 0 ) {
setSecond(sec - 1)
} else if (sec === 0 && min > 0) {
setMinute(min - 1)
if (min !== 0) {
setSecond(59)
}
}
}, 1000)
} else {
interval = setInterval(() => {
if (milliSec > 0 ) {
setMilliSec(milliSec - 1)
} else if (milliSec === 0 && sec > 0) {
setSecond(sec - 1)
if (sec !== 0) {
setMilliSec(9)
}
}
}, 100)
}
return () => clearInterval(interval)
});
const go = () => {
setIsRunning(isRunning => !isRunning);
}
const reset = () => {
setMinute(minute);
setSecond(second);
setMilliSec(0)
setIsRunning(false);
setIsMinuteSecondMode(true);
}
return (
<>
{minuteSecondMode ? <>
<span>{formatMinute}:</span>
<span>{formatSecond}</span>
</>: <>
<span>{formatSecond}.</span>
<span>{milliSec}</span>
</>
}
<div>
<button onClick={go}>{isRunning ? 'Stop':'Start'}</button>
<button onClick={reset}>Reset</button>
</div>
</>
);
};
728x90
반응형