왜 Hooks는 컴포넌트의 최상위 레벨에서 호출해야 하나요?

2023. 12. 29. 21:04React

728x90
반응형

hook을 작성할 때는 반드시 컴포넌트의 최상위 레벨 혹은 커스텀 훅 안에서만 작성할 수 있다.
즉, 조건문, 반복문, 함수 내부에서는 hook을 호출할 수 없다.

 

왜 이런 규칙이 생겼는지 알아보자!!

 

 

🔗 참고한 글

 

React hooks: not magic, just arrays

Untangling the rules around the proposal using diagrams

medium.com

 

State: 컴포넌트의 메모리 – React

The library for web and native user interfaces

react-ko.dev

 

 

 

 

useState를 호출하는 코드를 보면, 인자로 초기값만을 전달하고 있다.

const [index, setIndex] = useState(0);


어떤 state 변수를 참조하는 지에 대한 정보는 받지 않는다!

이렇게 useState에 전달되는 식별자가 없는데, 어떤 state 변수를 반환할지 어떻게 아는 것일까?? 😲

 

hook은 동일한 컴포넌트의 모든 렌더링에서 안정적인 호출 순서에 의존한다.
최상위 수준에서만 hook을 호출한다는 규칙을 따르면 hook은 항상 같은 순서로 호출된다.

 

 

이렇게 매 렌더링마다 동일한 순서로 호출되는

모든 hook은 컴포넌트마다 배열로 관리된다.

그리고

hook이 호출되는 순서에 따라서 렌더링 간에 어떤 hook인지 파악한다.

 

아래의 예제는 useState가 내부적으로 어떻게 작동하는지 간략화한 함수이다.

let componentHooks = []; // 컴포넌트의 모든 훅을 저장하는 배열
let currentHookIndex = 0; // 현재 처리 중인 훅의 인덱스

function useState(initialState) {
  let pair = componentHooks[currentHookIndex];
  if (pair) {
    // 첫 번째 렌더링이 아닐 경우
    // pair를 반환하고 다음 훅 호출을 위해 index를 증가한다.
    currentHookIndex++;
    return pair;
  }

  // 첫 번째 렌더링이라면, componentHooks[0]에 상태 pair를 생성해서 저장한다.
  pair = [initialState, setState];

  function setState(nextState) {
    // 상태 변경을 요청하면, 새 값을 현재 pair에 저장한다.
    pair[0] = nextState;
    updateDOM();
  }

  // 다음 렌더링을 위해 현재 pair를 hooks 배열에 저장하고, 
  componentHooks[currentHookIndex] = pair;
  // 다음 훅 호출을 위해 index를 증가한다.
  currentHookIndex++;
  return pair;
}

function updateDOM() {
  // 현재 훅 인덱스를 리셋한다.
  currentHookIndex = 0;
  let output = Gallery();

  // DOM을 출력 내용과 일치하도록 업데이트한다.
  nextButton.onclick = output.onNextClick;
  header.textContent = output.header;
  moreButton.onclick = output.onMoreClick;
  // ...

}

let nextButton = document.getElementById('nextButton');
let header = document.getElementById('header');
let moreButton = document.getElementById('moreButton');
// ...

// UI를 초기 상태와 일치하게 만든다.
updateDOM();

 

즉, 첫 번째 setState는 첫 번째 state 변수를 변경하고
두 번째 setState는 두 번째 state 변수를 변경한다.

 

이런식으로 몇 번째에 호출된 hook인지에 따라서 값을 식별하므로 순서가 보장되어야 하는 것!
그리고 그 순서를 보장하기 위해 조건문이나 반복문, 중첩된 함수 내부에서 hook을 호출하지 않고,

컴포넌트의 최상위 레벨에서만 작성하는 것이다. 😁

728x90
반응형

'React' 카테고리의 다른 글

[React] useFormState, useFormStatus  (1) 2024.02.12
[React] useRef, forwardRef, useImperativeHandle  (1) 2023.12.12
[Redux] Redux, React Redux, Redux DevTools  (1) 2023.10.03