동아리 부원 모집 활성화 / 비활성화를 toggle button을 통해서 편하게 조정할 수 있도록 만들고 싶었다.
우선 동아리 모집이 활성화 되어있는 상태를 받아와서 true / false에 따라 다른 값을 렌더링 시켜야 한다.
그래서 if 문을 통해 해당 상태 데이터가 !undefined 임을 확인하고 그 안에서 이런 식으로 만들어 주었다.
그런데
Uncaught Error: Rendered more hooks than during the previous render.
에러가 떴다.
그래서 if 문 바깥에
const [RecruitIsOpen, setRecruitIsOpen] = useState(true);
를 선언해주고
const RecruitState~ 위에 setRecruitIsOpen(data1.opened)를 적어주었다.
그랬더니
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
에러가 떴다.
구글링 해보니 가장 유명한 해결방법은
https://stackoverflow.com/questions/55265604/uncaught-invariant-violation-too-many-re-renders-react-limits-the-number-of-re
화살표 함수를 이용하라는 것이었다. (비단 stackoverflow에만 이런 답변이 있지 않았다.)
하지만 난 이미 화살표 함수를 쓰고 있다고 생각하는데 어떻게 해야하나라는 생각이 들었다.
RecruitState 내부 Button 태그에서 onClick하지 말고 RecruitState 자체에 onClick을 줘봤지만 여전히 같은 에러가 발생했다.
<RecruitState onClick={() => {setRecruitIsOpen((e) => !e)}}/>
통째로 if 문 밖으로 빼도 같은 에러가 발생했다.
일단은 return 부분은 삼항 연산자로 넣어주었다.
화살표 함수를 쓰라는 것의 의미를 알게 되었는데 setState를 onClick일 때만 바뀌게 하라는 것이다. 하지만 난 초기값을 넣어주어야 하는데...
초기값은
const [RecruitIsOpen, setRecruitIsOpen] = useState(data1.opened);
이렇게 넣었는데 처음 몇 번은 잘 작동하더니
Uncaught Error: Rendered more hooks than during the previous render.
이 에러가 발생했다...
난 useState의 초기값에 data1.opened의 값을 넣고 싶은데 그걸 특정한 action(ex: onClick()을 통한 화살표 함수 이용) 없이는 계속 에러를 뿜을 것이 분명했다.
data1.opened의 값을 && 같은 것을 이용해서 특정 컴포넌트를 보이게 할까 생각도 했지만 곰곰히 생각해보면 안 될 것이 분명했다.
4시간 정도 고민하니 새벽 2시가 넘어 일단 자야겠다고 생각해서 누웠는데 바로 해결 방법이 떠올랐다.
그냥 data1.opened의 값에 따라 useState의 초기값이 true인 것과 false 인 거 2개를 만들어서 넣어주면 되는 거였다.
쉽게 해결할 수 있는 것을 빙 돌아온 느낌이지만 덕분에 react-hook (useState, useEffect)에 대한 공부를 할 수 있는 시간이 되었다.
공식 문서도 읽어보고!
https://reactjs.org/docs/hooks-rules.html
useState는 비동기적으로 작동하기 때문에 setState()의 값이 즉시 업데이트가 되지 않을 수 있다.