"Maximum Update Depth Exceeded" Error

verdantgreeny·2025년 1월 24일

본캠프

목록 보기
31/56
무한루프에 빠진 모습

원래 있던 onClick을 삭제하고 onChange로 메달옵션을 변경하려고

    if (selectRadio === "1") {
      sortMedals();
    } else {
      sortTotalMedals()
    }  

를 넣었더니 무한루프가 발생했고 useEffect를 썼을 때 무한루프가 해결됐던 것이 생각이 나서 useEffect를 써보았다.

useEffect(() => {
    if (selectRadio === "1") {
      sortMedals();
    } else {
      sortTotalMedals()
    }  
},[sortMedals,sortTotalMedals])

그러나 위와 같이 넣었음에도 문제는 나아지지 않았다. 그래서 이번에는 실행에 대한 여부를 제한하면 되지 않을 까하여 아래와 같이 코드를 짰더니 무한루프는 빠져나왔지만 onchange가 되지 않았다.

 const [isInitialRender, setIsInitialRender] = useState(true);

  useEffect(() => {
    if (selectRadio === "1") {
      sortMedals();
    } else {
      sortTotalMedals()
    }  
  }, [sortMedals,sortTotalMedals,isInitialRender]);

답은 onchange 이벤트가 일어날 때 바꾸도록 만들어 줬어야 했다. useEffect는 sideEffect를 처리하기 위해 사용된다. 매번 컴포넌트가 렌더링 될 때 특정 조건에 의존하여 수행되며, 컴포넌트가 최대한 순수 함수를 유지할 수 있도록 도와주는 함수이다. 여기서 sideEffect는 함수 내 특정 동작이 함수 외부에 영향을 끼쳐, 프로그램의 동작을 이해하기 어렵게 만드는 행위(서버와의 통신, setTimeout, setInterval, 리액트 외부와의 상호작용)이다. useEffect의 경우 state를 변경하려 할 때 사용하는 것은 크나큰 실수였다. 단순히 무한루프를 해결해 주는 것이라고 생각했는데 어떤 코드를 작성할 때 제대로 된 개념을 알고 써야겠다는 생각이 들었다. 너무 쉬운 문제였는데 기초가 탄탄하지 못해서 계속해서 오류가 발생하는 것 같아 아쉽다.

useEffect 더 알아보기

useEffect는 컴포넌트가 렌더링이 된 후에 실행되기 때문에, 훅 내에서 setState와 같은 상태 업데이트 함수를 호출하면 컴포넌트가 다시 렌더링되고, 다시 훅이 실행된다. 이렇게 상태 업데이트 함수를 호출하면 무한 루프가 발생하여 위와 같은 오류가 발생한다.

useEffect는 기본적으로 컴포넌트가 렌더링될 때마다 실행된다. 이때, 훅이 상태를 업데이트하면 다시 렌더링되고 다시 훅이 실행되어 무한 루프가 발생한다. 이런 경우에는 훅의 의존성 배열에 필요한 상태나 프롭??을 추가하여 의존성이 변경될 때만 훅이 실행되도록 막아햐 한다.

따라서 훅에서 상태를 업데이트하거나 의존성 배열을 잘못 설정하면 계속해서 무한루프가 발생한다고 한다.

  const handleChange = (e) => {
    setSelectRadio(e.target.value);
    if (selectRadio === "1") {
      sortMedals();
    } else {
      sortTotalMedals()
    }  
  };
무한루프에도 빠져나오고 onchage도 정상적으로 작동한다.

+++ 추가 문제 +++

라디오 박스를 체크하면 반대의 결과값이 나온다. 그리고 무한루프에는 빠져나온 대신에 국가 추가 및 업데이트시에 맨 마지막에 추가가 된다.

    console.log(selectRadio);
    if (selectRadio === "1") { 
      sortTotalMedals()   // 원래 여기가 sortMedals(); 
    } else {
      sortMedals(); // 원래 이기가 sortTotalMedals() 
    }  

0개의 댓글