[웨일마켓] Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

Moon Hee·2022년 7월 13일
0

트러블 슈팅

목록 보기
17/26

회원가입 페이지 유효성 검사 에러메시지를 처리하다가 이런 에러가 발생했다.

react-dom.development.js:16317 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

다음 버튼을 누르기도 전에 화면 내용이 사라지는 현상이다. success가 되면 다음 페이지인 프로필 설정 페이지로 넘어가게 해주는게 가장 큰 로직이다. 그리고 success가 되려면 이메일과 비밀번호 유효성 검사를 통과해야한다. 내 느낌으로는 success를 판별하는 뭔가가 두 인풋값이 변할때마다 계속 체크를 하는데 너무 많이 변해서 브라우저가 무한렌더링 방지를 위해 에러메시지를 보여준 것 같다.

이 기능 만들면 저 기능 안되고의 반복이다...


🤔 혼자 덩그라니 있는 수상한 if 문 의심하기

아직은 리액트를 배우고 있는 단계라서 if문 쓸 때 어떤 점을 생각해야 하는지 잘 몰랐다. 저 이슈를 일으킨 코드는 이 부분이다.

최상위에서 유효성 검사를 하면 state 변화가 계속 일어난다.
지금 코드는 비밀번호 길이가 5자 이상이면,
렌더링 -> setState -> 렌더링 -> setState -> 렌더링 -> ... 무한반복에 걸린다.
즉, 상태가 바뀌든 안바뀌든 비밀번호가 5자 초과면 무조건 setIsValidPassword가 실행되는 상태이다.
그래서 state가 바뀔 때만 이 유효성검사를 실행되게 해야하는데 그걸 해주기위해 useEffect에 넣어줘야 한다.

여기서 리액트의 Form에 대해서 조금 공부를 하고 갈 것이 있는데, '상태'에 관한 것이다. 사실 이 문제해결과는 크게 상관 없지만 폼의 state에 대해서 알고 있어야 하는 내용이 것 같다.

➕ 제어 컴포넌트 이해하기(출처: 리액트 공식문서)

HTML에서 input 같은 폼 엘리먼트들은 사용자가 입력한 내용을 기반으로 state를 관리하고 업데이트한다. 리액트에서는 setState에 의해 업데이트된다.
하지만 폼은 기본적으로 사용자가 입력하는 것이기 때문에 state가 계속 변한다. 예를 들면 아이디나 비밀번호를 입력하는 중에도 state가 계속 변한다.
그래서 리액트는 폼 엘리먼트를 제어한다. 이렇게 리액트에 의해 제어받는 폼 엘리먼트를 제어 컴포넌트(controlled component)라고 부른다.

return (
	<form onSubmit={onSubmit}>
    	<label> 비밀번호
    		<input type="text" value={value} onChange={onChange} />
    	</label>
    	<button type="submit" />
    </form>
);

화면에 표시되는 값은 항상 state.value가 된다. 리액트 state를 업데이트 하기 위해 모든 키 입력에서 handleChange가 동작한다. 그래서 사용자가 입력할 때 보여지는 값이 업데이트 된다. 즉, input 값은 항상 리액트 state에 의해 결정된다.

리액트 공식문서 <폼> 바로가기
(공식문서 예제 class 컴포넌트로 나옴 주의...)


🔫 useEffect 사용하기

state가 바뀔 때만 해당 유효성 검사가 실행되게 해야하는데 그걸 해주기위해 if문을 useEffect에 넣어주면 해결된다.

useEffect(() => {
	setErrorMessage('');
  	if (password.length > 5) {
    	setIsValidPassword(true);
    }
}, [email, password]);

email과 password가 바뀔때만 if문을 실행하도록 하는 방법이다. '바뀌면'이 포인트인 것 같다. 6자부터 계속 실행되는 것에서 벗어날 수 있는 거다. 6자에서 7자 바뀔때 한번 7자에서 8자로 바뀔떄 한번... 이런식으로! Hook 간편설명서라는 포스팅도 올렸는데 실전에서 쓰려니까 하나로 모르겠는거 직접 써보니까 알 것 같다.

profile
프론트엔드 개발하는 사람

0개의 댓글