Hooks와 setInterval, 친해지길 바라

Kyle·2022년 9월 13일
0
post-thumbnail

타이머가 필요한 오늘의 프로젝트

페이지가 새로 렌더가 될 때마다 각 페이지에 머무는 시간을 측정하고 싶다.

useEffect에 setInterval을 넣어주면 해결이겠지?

해당 함수를 useEffect안에 넣어줬는데 seconds 값을 잘 불러오지 못하는 것 같다. 값이 0에서 1로 올라간 후 멈춰있는 문제가 생겼다.

setInterval 함수를 잘못 사용하여 이런 결과가 나오는건가 싶었는데 setInterval 함수에는 문제가 없어서 useEffect와 setInterval 함수가 같이 사용이 될 때 문제가 생기는 건가 싶어 검색을 해보았다.

문제가 생기는 지점은 useEffect가 count를 첫 렌더에서 잡기 때문에 일어난다. 첫 렌더에서 count는 0인데 이펙트를 재적용하지 않아서 setInterval에 있는 클로저가 항상 첫 렌더의 count를 참조하게 되는 것이다. seconds+1이 계속 1에서 멈춰 있던 이유가 있었다.

조금 더 구체적으로 파고든다면 리액트는 props와 state가 변한다면 변한 부분의 렌더링을 지운 후 다시 렌더링을 한다(virtual DOM). useEffect도 이러한 방식으로 의존성 배열에 따라 지난 effect를 지우고 새로운 이펙트를 설정하는데 setInterval()은 지난 값을 잊지 않기 때문에 문제가 생기는 것이다. setInterval()은 값을 직접 교체하지 않는다면 기존의 props와 state를 계속 참조하게 된다. react와 setInterval의 작동 원리의 차이로 해당 문제가 일어나는구나 생각이 들었다.

이를 해결하기 위해서는 두가지 방법이 있다.

첫째, 업데이트폼을 사용해보자

useState로 지정해줬던 seconds를 사용해서 setSeconds( seconds + 1 )을 사용하는 것이 아니라 새로운 값을 계속 받아올 수 있도록 업데이터 폼과 함께 사용해야 한다. 코드를 setSeconds( s => s + 1 )로 수정해보자. 새로운 값을 참조할 수 있도록 하여 문제를 해결하는 방향이다.

두번째, useRef를 사용해보자

useRef를 통해서 현재 어디에서 값을 참조하고 있는지 지정을 해줘야 한다. useRef()를 기본값과 함께 지정을 한 후 setSeconds( useRef()지정한이름.current+=1 ) 로 수정을 해보자. 렌더링 이후의 callback을 참조할 수 있도록 하여 문제를 해결하는 방향이다.

아차모먼트

setInterval()과 react의 차이를 인지하고 이를 해결하기 위해서 어떤 상황에서 어떤 해결책을 사용할 수 있는지 알게 되었다.

혹시 제가 잘못 기재했거나 수정해야 할 사실이 있다면 따끔한 회초리 부탁드립니다,,

profile
불편함을 고민하는 프론트엔드 개발자, 박민철입니다.

0개의 댓글