코딩 공부 일지/React JS

리액트에서 useRef를 이용해서 현명하게 setInterval 사용하기

헬로코딩 2022. 5. 25. 21:56
728x90

React와 setInterval의 관계

리액트는 상태값이 변하면 재렌더링을 한다. 그래서 리액트에서 상태라는 개념에 대해 알고 있어야 앞으로의 내용이 이해가 가능하다. 

 

아래 예제는 1초에 한번씩 count의 숫자를 1씩 증가시켜서 렌더링을 하도록 만드는 것이다. 문법적으로는 잘 동작하는 코드처럼 보이지만, 리액트에서는 상태값이 변화될 때 마다 재렌더링이 되기 때문에 setInterval 함수가 여러번 다시 실행되어 에러가 난다. 나의 경우에는 숫자가 변하는 속도가 갈수록 빨라졌다. (setInterval이 여러 번 실행되어 중첩된 것으로 추정)

import { useState } from "react";

export default function Example() {
  let [count, setCount] = useState(0);

  setInterval(() => {
    setCount(count += 1);
  }, 1000);

  return (
    <div>{count}</div>
  )
}

useEffect를 활용하여 setInterval 한번만 등록하기

setInterval이 여러번 실행되는 것을 방지하기 위해 useEffect를 통해서 처음 렌더링 시에만 setInterval을 등록해준다.

import { useEffect, useState } from "react";

export default function Example() {
  let [count, setCount] = useState(0);

  useEffect(() => {
    setInterval(() => {
      setCount(count += 1);
    }, 1000);
  }, []);

  return (
    <div>{count}</div>
  )
}

useEffect의 dependency에 아무것도 선언하지 않아서 컴포넌트가 최초 마운트 될 때만 setInterval이 등록되도록 만들었다. 그러나 이 방법도 완벽한 방법은 아니다. 

리액트에서 주는 경고 메세지를 보면, useEffect가 다시 렌더될 때마다 변수 값을 잃어버릴 수 있다고 경고하고 있다.

useRef를 사용하여 interval을 기억하도록 만들기

useRef는 current에 참조 값을 저장해두어 사용하는 훅(Hook)이다. useRef에 interval을 저장해두어 사용한다.

import { useEffect, useState, useRef } from "react";

export default function Example() {
  let [count, setCount] = useState(0);
  const interval = useRef();

  useEffect(() => {
    interval.current = setInterval(() => {
      setCount(prev => prev + 1);
    }, 1000);

    return () => {
      clearInterval(interval.current);
    }
  }, []);

  return (
    <div>{count}</div>
  )
}

useEffect의 return 값으로 역시 clearInterval을 사용하여 메모리 누수를 방지한다. useEffect의 return 값으로 clearInterval을 호출하면 컴포넌트가 언마운트 될 때 실행된다.

728x90