Library | Framework/React

[React] setInterval, setState를 같이 쓸 때 오류 해결

나는김혜린 2022. 5. 30. 21:20

ㅇ...이게 머노...?

머선 일이구

3초마다 배경색을 바꿔주려고 했는데 처음엔 잘 되다가 몇 분 지나면 광란의 파티가 된다......

왜 그런지 Console 창에 color를 띄워보니 막무가내로 바뀌었다가 유지되다가 난리였다...

const [color, setColor ]= useState("#F9CC82");
const colorChange = useRef<any>(null);

useEffect(() => {
    setInterval(() => {
    	console.log(color);
        if(color === "orange") setColor("pink")
        else if(color === "pink") setColor("purple")
        else if(color === "purple") setColor("orange");
        colorChange.current.style = `background-color: ${color};`;
    }, 3000);
}, [])

위 코드가 그 문제의 코드이다.

const [color, setColor ]= useState("#F9CC82");
const colorChange = useRef<any>(null);
useEffect(() => {
    setInterval(changeColor, 2000)
}, [color])
function changeColor() {
    console.log(color);
    if(color === "#F9CC82") {
        console.log("change 1");
        setColor("#E2B4BA");
    } else if(color === "#E2B4BA") setColor("#F9CC82");
    colorChange.current.style = `background-color: ${color};`;
}

사실 setInterval 함수에 대해 잘 모르는 상태로 사용해본 거라서

setInterval을 구글링하면서 찾아보니 함수형태로 사용하는 경우도 있길래 사용해봤다.

그리고 color state가 바뀔 때마다 렌더링하게끔 했는데........ 이렇게 하니 맨 위 영상처럼 난리 부르스가 났다.

 

그래서 어떻게 고쳤는가?

const [color, setColor ]= useState("#F9CC82");
const side = useRef<any>(null);

useEffect(() => {
    const interval = setInterval(() => {
        if(color === "#F9CC82") {
            setColor(color => "#E2B4BA");
        } else if(color === "#E2B4BA") setColor(color => "#C6B5D7");
        else if(color === "#C6B5D7") setColor(color => "#A7D0D7");
        else if(color === "#A7D0D7") setColor(color => "#F9CC82");
        side.current.style = `background-color: ${color};`;
    }, 3000);
    return () => clearInterval(interval);
}, [color])

위 코드가 최종본이다.

일단 setInterval에서 조건에 따라 색을 바꾸고, setInterval의 반환값을 interval 변수에 할당한다.

여기서 끝내면 setState가 무진장 실행된다.

따라서 clearInterval을 해주어 색바꾸는 동작을 한 번만 하게끔 만들어주면 해결!

뭐가 문제였지?

const [number, setNumber] = useState(0);
useEffect(() => {
    const interval = setInterval(() => {
      console.log(number);
      setNumber((number) => number + 1);
    }, 1000);
}, [number]);

위 코드를 실행해보자.

그러면 위 사진과 같이 무한으로 Console에 출력이 되고, 일정하게 증가하는 것이 아니라 무작위로 출력된다.

이유는 아직 잘 모르겠다... setState가 비동기적으로 실행돼서 그런 거 아닐까...?

아무튼 저 에러를 해결하려면 clearInterval을 사용한다.

const [number, setNumber] = useState(0);
useEffect(() => {
    const interval = setInterval(() => {
      console.log(number);
      setNumber((number) => number + 1);
    }, 1000);
    return () => clearInterval(interval);
}, [number]);

clearInterval 함수는 실행중인 Interval 함수를 멈추는 것인데, 이게 있어야 setNumber 함수가 3초에 한 번 실행된다.


이거 오류 이유가 너무 궁금했는데 아무리 구글링해도 안 나와서 옾챗에 물어봤는데 다 모르신다...

아시는 분은 댓글 남겨주세요...