진짜 삼일 넘게 고민하고 찾아보고 내 맘대로 고쳐보고 하다가 답답해 뒤지겠어서 Stackoverflow에 질문 올렸다가 즉시 해결 (내가 바보였음)
나는 useEffect를 쓰다가 invalid hook call이 떴다.
오류 코드는 아래와 같다.
const [hand, setHand] = useState({myhand:-1, comhand:-1})
function setWinner(h){
useEffect(() => {
findWinner(hand.myhand, hand.comhand)
}, [hand]);
setHand({myhand:h, comhand:Math.floor(Math.random()*10)%5});
}
invalid hook call 이 뜬 이유는
함수 내에서 useEffect를 호출해서였다.
useEffect를 함수 밖으로 꺼내주면 된다.
const [hand, setHand] = useState({myhand:-1, comhand:-1})
useEffect(() => {
findWinner(hand.myhand, hand.comhand)
}, [hand]);
function setWinner(h){
setHand({myhand:h, comhand:Math.floor(Math.random()*10)%5});
}
React 공식 문서에 의하면 오류는 다음 세 가지가 있다.
React와 React DOM의 버전 불일치
hooks 규칙 위반
hooks를 호출할 때 지켜야 하는 규칙은 다음과 같다.
✅최상위(at the Top Level)에서만 Hook을 호출
반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하면 안 된다.
✅오직 React 함수 내에서만 Hook 호출
Hook을 일반적인 js 함수 내에서 호출하면 안 된다.
대신 react 함수 컴포넌트에서 호출하거나, custom hook 에서 호출해야 한다.
두 개의 리액트 패키지가 복사됨 (참조)
Hook은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수입니다.
함수형 컴포넌트의 단점이었던 state 이용 불가와, lifecycle 관리를 도와주는 함수이다.
hook이 존재하기 전에는 class component에서 render()를 해 주어야만 했다. 그러나 hook 탄생 이후에는 functional component에서 모든 것을 해결할 수 있다.
이전까지 react는 class component를 주로 사용했다.
그러나 class component는 분명한 단점들을 가지고 있었다.
- 문법이 어려워 기본적 js 문법사항을 알아야 다룰 수 있다.
- 축소하기 어렵다.
- reloading의 신뢰성이 떨어진다.
- 최신 기술을 적용하기 어렵다.
그럼에도 명확한 장점이 있였다.
- state를 사용할 수 있다.
- life cycle을 직접 관리할 수 있다.
(state: 컴포넌트의 렌더링 결과물에 영향을 주는 데이터. 컴포넌트 안에서 관리된다.)
(life cycle: 생애주기는 컴포넌트가 실행, 업데이트, 제거될 때 발생하는 이벤트들을 통틀어 가리키는 말이다.)
이 장점들을 활용할 수 있도록 도와주는 것이 hook이다.
대표적인 Hook은 다음 두 가지가 있다.