useEffect에 clearTimeout 사용하기

lee dango·2022년 7월 28일

setTimeOut이 두 번 실행되다

문제발생

프린트하려는 화면을 라우터로 넘겨서 프린트하고자 하는 화면으로 이동한다. 그리고 window.print()를 실행시켜 이 라우터 화면을 프린트를 할 수 있는 창을 띄운다. 이 프린트 창이 닫히면 이전의 화면으로 돌아가게 처리를 해두었다.
처음에는 잘 작동되다가 어느날 이전의 화면으로 돌아가서 다시 프린트 화면이 띄워지는 에러가 발생했다.

  setTimeout(() => {
    goPrint();
  }, 1500);
   
  const goPrint = () => {
    window.print();

	// ...
    if (history.location.pathname !== `${ROOT.MAIN}/${lnb}`)
      history.push({
        pathname: `${ROOT.MAIN}/${lnb}`,
      });
  };
  
  • 라우터로 화면이 넘어갔을 때 setTimeOut을 걸어두고 window.print()를 실행하고 있었다.
  • location.pathname으로 조건을 걸어보았으나, 다른 라우터로 돌아가도 프린트화면과 같은 pathname이 찍혀서 처리되지 않았다.

해결

조건을 걸어도 되지 않아서, setTimeout에 어떠한 제어를 해줘겠다고 생각했다. 라우터가 바뀔 때 useEffect가 발생하고 있어서 여기에 함수를 실행시키지 않게 만들어야 겠다고 생각했다. 그래서 찾게 된 방법이 clearTimeout이었다.

  const printTimer = setTimeout(() => {
    goPrint();
  }, 1500);
  
    if (location.pathname === `${ROOT.PRINT}`) {
    printTimer;
  }
  
  useEffect(() => {
	// ...
    clearTimeout(printTimer);
  }, [useLocation]);
  

다시 이전의 경로로 돌아갔을 경우 두 번 발생하던 setTimeout이 한 번으로 그쳤고, 프린트 버튼을 누를 때(다시 발생시킬 때)는 정상적으로 실행되는 것을 확인했다.

useEffect에서 clearTimeout을 하는 이유

setTimeout은 지정한 시간이 지나면 인수로 받은 함수를 실행한다.
하지만 지정한 시간이 지나기전에 useEffect가 다시 발생하면 setTimeout이 다시 실행되어서 결국 setTimeout에 지정한 함수가 두 번 실행하던 것이었다.

이같은 일을 방지하려면 지정된 시간이 지나기 전에 clearTimeout로 제거해줌으로써 항상 시간마다 1번만 실행되는 것을 보증할 수 있게 됐다.


참고 링크

0개의 댓글