Web/React

리액트 훅은 왜 조건문 안에서 쓸 수 없을까?

728x90
반응형

그 동안 리액트훅을 사용할 때 리액트 컴포넌트 함수의 최상위에서 훅을 항상 호출해서 사용했기 때문에 너무나 당연하게 조건문이나 반복문 안에서 사용할 생각을 하지 않았다. 하지만 왜 그렇게 하는 것인지에 대해 생각해보지 못했고, 오키 질문에도 나처럼 궁금해 하시는 분들이 계신 거 같아 이번 기회에 정리해서 함께 공유하면 좋을 거 같다.

 

https://okky.kr/articles/797461

 

실제로 현재 진행중인 프로젝트에서 조건문 안에 useEffect 훅을 호출하면 아래와 같이 린트 에러가 발생한다. 에러 메세지를 읽어보면, 리액트 훅은 렌더링 시 반드시 동일한 순서로 불려야 하기 때문에 조건적으로 호출되면 안된다고 말하고 있다.

 

실제 리액트의 공식문서에서도 리액트 훅과 관련된 규칙으로 다음과 같이 안내되어 있다.

- 반복문, 조건문 혹은 중첩된 함수 내에서 hook을 호출하지 않아야 합니다.
- 항상 React 컴포넌트 함수의 최상위(at the top level)에서 Hook을 호출해야 합니다.
- 이 규칙을 따르면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장됩니다.
- 따라서 React가 useState, useEffect를 여러번 호출되는 중에도 hook의 상태를 올바르게 유지할 수 있게 해줍니다.

 

만약 아래의 경우처럼 조건문 안에 useState 훅을 넣는다면 두 번째 훅의 index는 1이 돼야 하지만 조건에 따라 첫 번째 훅이 실행되지 않을 수도 있으므로 index가 0이 될 수도 있다는 문제가 있다. 따라서 순서가 보장되지 않으므로 아래처럼 사용해서는 안 된다. 리액트훅은 일반적인 자바스크립트 함수 내에서 호출하면 안 되고, 리액트 함수 컴포넌트에서 훅을 호출하거나 커스텀훅에서 훅을 호출해서 사용할 수 있다.

 

function component() {
  if (Math.random() > 0.5) {
    const [countA, setCountA] = React.useState(0);
  }
  
  const [countB, setCountB] = React.useState(1);

  return {
    //...
  };
}

 

 

혹시나 이런 규칙을 잊고 리액트 훅을 잘못 호출해 사용하는 경우에는 설정된 린트를 통해 에러를 발생시킬 수 있다. 참고로 Create React App에는 아래와 같은 플러그인이 기본적으로 포함되어 있다.

 

// ESLint 설정 파일
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

 

 

 

 

 

참고 문서

https://ko.reactjs.org/docs/hooks-rules.html

 

Hook의 규칙 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

반응형