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 |