useEffect 안에서 setInterval 쓰게 해주세요

MM·2023년 10월 3일

make it worth

목록 보기
7/10
post-thumbnail

가능은 하다. 딱 한번.

useEffect(()=>{
	setInterval(()=>{console.log("한번만 찍힌다.")}, 1000);
},[])

위와 같이 useEffect 내에서 setInterval을 쓰면 한번만 찍힌다.
왜지? 한번만 실행되도 클로저 내에서 setInterval은 계속 동작할 거라고 생각했는데..

그런데 놀랍게도,

😳 setInterval은 함수가 아니라 메서드다!

그러니까 이게 아니라

function setInterval(){
  ...
}

  
setInterval();

이거란 말이다

const window={
	setInterval: function(){...}
}

window.setInterval(); //window 생략. 글로벌 함수이나 기본적으로 전역객체의 메서드이다.

-> 즉, 클로저를 형성하지 않는다!!
-> 그러니 상위 함수가 사라지면, 같이 그냥 사라진다..
-> 🤔 그럼 어떻게 시작하자마자 setInterval을 쓰게 할까?

모든 것은 훅으로 해결된다

useInterval

export function useInterval(callback, delay) {
  //클로저 대용으로 사용하기 위해 ref를 만들어준다.
  //-> 함수 컴포넌트가 리렌더링되어도 useRef 객체는 초기화되지 않고 유지되니까!
  const savedCallback = useRef();
  
//초기 세팅
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

왜 tick함수를 useEffect안에서 정의했나?

setInterval이 실행되고 있는 스코프 내에서 savedCallback을 참조하기 위해!
이렇게 함으로써 setInterval이 실행될 때마다 항상 최신의 callback 함수가 호출된다!

profile
중요한 건 꺾여도 그냥 하는 마음

0개의 댓글