이유)
export const useCountDown = (callback: () => void, delay: number, isCount: boolean) => {
const savedCallback = useRef<() => void>(callback);
useEffect(() => {
if (!isCount || !delay) {
return;
}
console.log("setInterval 실행");
//현재 저장된 콜백 함수 호출
const tick = () => {
savedCallback.current();
};
const timerId = setInterval(tick, delay);
return () => {
console.log("타이머 종료", timerId);
clearInterval(timerId);
};
}, [isCount]);
};
기존 타이머 로직에서 새로 들어온 initialTimer를 state값이 인식하지 못하는 현상이 발생
export const useCountDown = (initialTime: number, ms: number) => {
const [time, setTime] = useState(initialTime);
useEffect(() => {
console.log("initialTime", initialTime); //5
console.log("time", time); // 0
...
},[initialTime])
이유) React 생명주기와 관련 이슈
해결)
의존성 배열에 state값인 [time]을 넣어 실행하였지만 기존 타이머가 작동되고 있는 과정에서 또 다른 timer가 작동되는 error 발생
새로운 레퍼런스를 참고하여 로직을 변경
기존) timer값을 인자로 전달받아 state에 저장한 후 setInterval를 사용하여 변경된 state값을 return하는 방식이 아닌
현재) useCountDown(() => setCount((prevCount) => prevCount - 1), 1000, isTimer);
setState인 callback함수로 전달받아 사용하는 방식을 택하였다.
맨 위의 개발내용의 로직을 보시면 아시다시피 count가 변화하더라도 useCountDown 내부의 useEffect 훅이 불필요하게 다시 실행되지 않는다는 것과 기존 로직에 비해 가독성이 높아진 걸 볼 수 있다.
https://www.dhiwise.com/post/enhance-user-experience-implementing-a-react-hooks-timer
https://velog.io/@yeyo0x0/React-React-Hooks%EC%97%90%EC%84%9C-setInterval-%EC%82%AC%EC%9A%A9-%EB%AC%B8%EC%A0%9C