JS/React

React - setInterval & setTimeout

shin96bc 2024. 3. 9. 17:50

setInterval

기능

 

사용법

 

주의점

 

초기값이 유지되는 문제

// # 문제 발생 코드const [productDataIndex, setProductDataIndex] = useState(0);

  useEffect(() => {
      const slideInterval = setInterval(() => {
          if (productDataIndex >= productDataList.length - 1) {
              setProductDataIndex(0);
          } else {
              setProductDataIndex(productDataIndex + 1);
          }
      }, 3000);

      return () => {
          clearInterval(slideInterval);
      };
  }, []);
// 이렇게 useEffect 에 2번째 인자값으로 [] 를 넘기게되면 state 값이 바뀔 때// 리랜더링이 발생해서 useEffect 를 다시 호출하게 됩니다. 그래서 state 값이// 계속 0 으로 초기화됩니다.

// # 해결법1(interval 이 여러개가 있으면 하나만 작동합니다.)//  useEffect 의 2번째 인자값에 아무것도 넘기지 않고 사용합니다.//  그렇게되면 useEffect 가 리랜더링되지 않기 때문에 정상적으로 작동합니다.const [productDataIndex, setProductDataIndex] = useState(0);

  useEffect(() => {
      const slideInterval = setInterval(() => {
          if (productDataIndex >= productDataList.length - 1) {
              setProductDataIndex(0);
          } else {
              setProductDataIndex(productDataIndex + 1);
          }
      }, 3000);

      return () => {
          clearInterval(slideInterval);
      };
  });

// # 해결법2(props 문제 발생)//  updater function 을 사용합니다.//  그러나 이 방법은 props 가 바뀔 때 같은 문제가 발생합니다.const [productDataIndex, setProductDataIndex] = useState(0);

  useEffect(() => {
      const slideInterval = setInterval(() => {
          if (productDataIndex >= productDataList.length - 1) {
              setProductDataIndex(0);
          } else {
// updater function 사용
              setProductDataIndex(productDataIndex => productDataIndex + 1);
          }
      }, 3000);

      return () => {
          clearInterval(slideInterval);
      };
  }, []);

// # 해결법3//  useRef 를 사용합니다.//  useRef 는 값이 변화하더라도 리랜더링을 발생시키지 않기 때문에 useEffect 를//  다시 호출하지 않아서 문제가 해결됩니다.const [productDataIndex, setProductDataIndex] = useState(0);
  const saveCallBack = useRef();

  const callBack = () => {
      if (productDataIndex.current >= productDataList.length - 1) {
          productDataIndex.current = 0;
      } else {
          productDataIndex.current = productDataIndex.current + 1;
      }
  };

  useEffect(() => {
// useRef current 에 콜백함수를 담아줍니다.
      saveCallBack.current = callBack;
  });

  useEffect(() => {
      const saveCallBackCurrent = () => {
          saveCallBack.current();
      }
      const inteval = setInterval(saveCallBackCurrent, 3000;

      return () => {
          clearInterval(inteval);
      };
  }, []);
// 이렇게 해주면 state 가 변해서 리랜더링이 발생할 때 새로운 상태를 반영한 새로운// 콜백함수가 saveCallBack 의 current 에 저장됩니다. 그러면 객체의 property 가// 되므로 자유롭게 변경이 가능하고, 다음 interval 에서는 새로운 콜백을 반영한 interval 이// 실행됩니다.

 

setTimeout

기능

 

사용법

 

state 와 useEffect 와 함께 사용합니다.

// 3초마다 다음 상품으로 변경const [productDataIndex, setProductDataIndex] = useState(0);
// 시간초const [slideSeconds, setSlideSeconds] = useState(3);

  useEffect(() => {
// 1초 마다 한번씩 시간초를 1씩 감소시킵니다.const slideTimer = setTimeout(() => {
          setSlideSeconds(slideSeconds - 1);
      }, 1000);
// 시간초가 0이 되면 다시 시간초를 3으로 증가시킵니다.if (slideSeconds < 1) {
          if (productDataIndex >= productDataList.length - 1) {
              setProductDataIndex(0);
          } else {
              setProductDataIndex(productDataIndex + 1);
          }
          setSlideSeconds(3);
// Timeout 이 계속 메모리에 쌓이는걸 방지하기위해서// 새로 호출될때마다 매번 지워줍니다.clearTimeout(slideTimer);
      }
      console.log('productDataIndex2 = ' + productDataIndex);
      return () => {
          clearTimeout(slideTimer);
      };
  });

 

주의점

 

setInterval 과 setTimeout 의 차이점

setInterval

  • 기본 동작이 반복적으로 실행됩니다.
  • 실행중에 다른 setInterval 로 인해 함수가 호출되면 실행되던 함수는 종료됩니다.

setTimeout

  • 기본 동작이 한번만 실행됩니다.
  • 실행중에 다른 setTimeout 로 인해 함수가 호출되도 기존에 실행된 함수에 영향을 주지 않습니다.

'JS > React' 카테고리의 다른 글

React - 로그인 정보 관리(Redux 사용)  (0) 2024.03.09
React - Atomic Design 이란?  (0) 2024.03.09
React - ckEditor 사용법  (0) 2024.03.09
React - 포트번호 변경하기  (0) 2024.03.09
React - React Context  (0) 2024.03.09