트러블 슈팅 React에서 스톱워치 구현시 setInterval 주의사항
Description: 스톱워치 구현시 생각보다 어려웠던 렌더링 컴포넌트였어서 이를 구현하는 해결과정입니다.
현재 노트: KR-210.00 b
상위 분류: KR-210 렌더링 및 UI or UX
#문제해결_경험
https://github.com/murphybread/project-log
웹사이트의 타이머를 React로 구현하는 과정에서 마주쳤던 렌더링 문제를 해결한 경험입니다.
스톱워치 구현시 숫자가 제대로 렌더링 안되는 문제
처음 시도에서는 useEffect를 최대한 지양하고자 업데이트 되는 시간을 다음과 같이 구현하였습니다.
const intervalId = setInterval(() => setTime((prev) => prev + 10), 1000);
하지만 이렇게 하면 시간이 비정상적으로 누적량이 점점 증가해지게됩니다
그 이유는 해당 10초마다 값이 증가하고 이에따라 재 렌더링 되며 다시 setInterval함수가 쌓이기 때문입니다. 처음에는 prev를 업데잍트 하는 setInterval이 한 개지만, 점점 누적되면서 10ms마다 수십개의 setInterval로 인해 수치가 급격하게 상승하게 됩니다.
이런 문제를 해결하기 위해 useEffect
를 사용하게 됐습니다.
기존의 intervalID를 업데이트 하는데 useEffect의 초기배열을 []
로 설정해줌으로써 마운트시에만 setInterval 1개가 업데이트하게 되됩니다.
또한 Striced Mode의 경우 useEffect의 검증을 위해 두번의 마운트가 일어남으로 clean up 함수를 추가해줍니다.
const useEffct(() => {
let intervalId;
intervalId = setInterval(() => {
setTime((prev) => prev + 10);
}, 10);
//cleanup 함수
return () => clearInterval(intervalId);
}, [])
여기에 추가로 보통의 Timer처럼 동작,정지를 구현하기 위해 조건을 수정해줍니다.
useEffect(() => {
let intervalId;
if (isRunning) { // isRunning동안 timer 숫자 업데이트
intervalId = setInterval(() => {
setTime((prev) => prev + 10);
}, 10);
}
return () => clearInterval(intervalId);
}, [isRunning]); // isRunning 상태가 변경될 때마다 실행
해결하면서 생각해본점
시간에 따라 빠르게 변화하는 렌더링시 State와 Update 주의 깊게 생각해보기
시간에따라 렌더링이 되는 경우 그 업데이트되는 State를 무엇으로 어떻게가 중요하다고 느꼈습니다. 단순한 클릭이나 fetch등이 아니라 수십번이나 수백번이넘는 렌더링이 발생하며, 이에 따라 State를 잘못 설정하면 큰 문제가 발생할 수 있는것이었습니다.