useState/useRef 와 setTimeout/setInterval
useState/useRef 와 setTimeout/setInterval
setTimeout/setInterval 에는 useRef
-
useState 와 useRef
-
useState
상태 유지 값과 그 값을 갱신하는 함수를 반환하며 state 변할 시 리렌더링 큐에 등록
-
useRef
.current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체 반환
반환된 객체는 컴포넌트 전 생애유지 통해 유지됨
-
-
setTimeout/setInterval 에서의 차이
-
useState
const [number, setNumber] = useState(0) let timer = setInterval(()=> { setNumber(number + 1) console.log(number) }, 1000) // 0 loop
1초 단위로 0 만 출력
-
-
useRef
const number = useRef(0) let timer = setInterval(()=> { number.current = number.current + 1 console.log(number) }, 1000) // 0, 1, 2, 3, 4
1초 단위로 0 부터 1씩 더해서 출력
-
왜 차이가 생기냐?
-
useState
prevState 와 nextState 를 비교하고 변경함
setInterval 의 내부 callback 의 closure 에는 prevState 를 참조함
참조로 인하여 prevState 는 메모리에 남게되고 가비지 컬렉터의 영향을 받지 않음
setStae 로 state 를 변경하더라도 closure 에 의해 state 값은 변경되지 않고 console 에는 같은 값이 찍힘
-
useRef
순수한 JS 객체를 생성함
useState 처럼 값을 비교하는 과정이 없음
.current 로 값을 변경하면 JS 객체도 그래도 변경됨
setInterval 의 내부 callback 의 closure 에는 변경되는 .current 를 참조함
.current 로 값을 변경 시 값은 변경되고 console 에는 다른 값이 찍힘
-
-
setInterval/setTimeout 에 useState 를 사용하고 싶다면?
const number = useRef(0) const [numberState, setNumberState] = 0 let timer = setInterval(()=> { number.current = number.current + 1 setNumberState(number.current) console.log(number) }, 1000) // 0, 1, 2, 3, 4
state 값을 참조하는게 아니라 useRef 값을 참조하며 값 변경
-
결론
setTimeout/setInterval 에는 useRef!
리렌더링에 영향을 주지 않는 가변형 값에도 useRef!