Invalid Hook call 에러가 나는 원인에는 여러가지가 있는데, Hook에 대해서 잘 모르는 상태로 썼을때 에러가 날 확률이 높아진다.
특히 커스텀 Hook을 만들어 사용할때 이런 개념들을 모르고 쓰면 코드를 짜기도 어렵지만 디버깅할 때 상당히 골치아파진다.
use*로 시작하는 여러가지 Hook을 하나로 묶기 위해그러면 useEffect와 useMemo, useCallback의 차이를 알아보고 적재적소에 활용하여 에러를 마주칠 확률을 낮춰보자.
뭔가가 바뀌면 어떤 동작을 자동으로 실행하기 위해 사용useEffect(() => {어떤 동작}, [뭔가]);
useState와 함께 사용하는 예시const [ state, setState ] = useState('idle'); // 프로세스의 진행상태를 저장하는 state
useEffect(() => {
	if (state === 'success'){ // state가 success일때만 if문이 실행된다.
    	console.log("PROCESS DONE!! <<success>>");
        setState('idle'); // state를 초기상태로 돌려준다.
    }
}, [state]); // 프로세스가 idle -> pending -> success/fail로 바뀔 때마다 useEffect로 감싼 부분이 실행된다.
state는 코드는 프로세스가 진행됨에 따라 idle, pending, success or fail로 업데이트 된다. 상태가 없데이트 될때마다 useEffect에 전달한 콜백함수가 실행이 되는데, 내부에 if문이 있기 때문에 console.log가 되는 것은 success일때 뿐이다.원하는 타이밍에 호출시킬 함수를 만들기 위해 사용(함수가 반환됨)const [ food, setFood ] = useState('샐러드');
const [ menuAsked, setMenuAsked ] = useState(false);
useEffect(() => {
  if (menuAsked === true){
    printMenu();
    setMenuAsked(false); // state를 초기상태로 돌려준다.
  }
}, [menuAsked])
const printMenu useCallback(() => {
	console.log(`[ Today's Dinner Menu : ${food} ]`);
}, [food]);
menuAsked의 상태가 바뀔때마다 useEffect의 인라인 콜백함수가 실행되고, menuAsked의 상태가 true라면 printMenu 함수가 호출된다. 코드가 실행되는 동안 food의 상태가 바뀌지 않는다면 printMenu 함수의 내용도 바뀌지 않는다.| 동작 | food | menuAsked | printMenu 함수 변화 | 출력 | 
|---|---|---|---|---|
| 최초 상태 | '샐러드' | false | X | - | 
| setFood('고추장 삼겹살') | '고추장 삼겹살' | false | O | - | 
| setFood('갈치 구이') | '갈치 구이' | false | O | - | 
| setMenuAsked(true) | '갈치 구이' | true | X | [ Today's Dinner Menu : 갈치 구이 ] | 
setMenuAsked를 사용하면 menuAsked의 상태는 true가 되지만, 메뉴를 프린트 한뒤에는 다시 false로 초기화 된다.setFood는 printMenu 함수에만 영향을 주고 setMenuAsked는 메뉴의 출력에만 관여한다.useCallback은 원하는 타이밍에 실행시킬 함수를 만드는데 사용useMemo는 원하는 값을 업데이트하기 위해 사용const person = useMemo(
    () => (
      <Person
        name={name}
        song={favoriteSong}
      />
    ),
    [name, favoriteSong]
  );
useEffect vs useCallbackuseEffect는 어떤 값의 변화가 동작을 자동으로 불러오도록 하고 싶을때,useCallback은 어떤 값이 변했을때 특정 동작을 값에 따라 다르게 실행시키고 싶거나 원하는 타이밍에 어떤 동작을 실행시키고 싶을때 적합하다.state를 바라보고 있다가 effect를 주는 것인데 이때의 effect는 멱등성이 유지된다.
그에 비해 useCallback은 state에 따라 다른 동작을 하는 함수를 리턴할 수 있을므로 동작을 state에 따라 다르게 주고 싶을때 유용하다.
useMemo는 값을 리턴하며, 최적화에 방점이 찍힌다. 
처음 React를 공부하기 시작했을때 용도가 비슷해보이는 것이 여러개 있어 어떤 때에 무엇을 써야할 지 몰랐는데, 사용하다보니 필요한 곳을 알게되는 것 같다. useEffect, useCallback, useMemo도 글로 이해하려는 것보다는 계속해서 사용해보고 예시를 많이 보는게 이해가 빠르게 될 것 같다.
useState와 useMemo의 사용처 비교// b와 c를 더한 값이 a가 되는 경우
const a = useMemo(() => {b + c}, [b, c]);
// useState를 쓸 수 밖에 없는 상황
const [ name, setName ] = useState('');
const [ email, setEmail ] = useState('');
(생략)
// 1. get data from server
fetch(domain).then((res) => setName(res.data.name));
(생략)
// 2. get data from user input
return (
  <Form>
         <label css={labelStyle} htmlFor='email'> Email </label>
	 <input
            type='email'
	    id='email'
            value={email}
            (...)
            onChange={(event) => setEmail(event.currentTarget.value)}
         />
  </Form>
)
도움이 많이 되었습니다. 감사합니다!