본문 바로가기
Web/React.js

[STUDY] Hook의 규칙

by 폴우정킴 2021. 3. 23.
  • Hook는 자바스크립트 함수이다.
  • Hook를 사용할 때 두 가지 규칙을 준수해야 한다.
  • 규칙들을 강제하기 위해 linter 플러그인을 제공하고 있다.

최상위(at the Top Level) 에서만 Hook를 호출해야 한다

  • 반복문, 조건문, 중첩된 함수 내에서 Hook를 호출하면 안된다.
  • 리액트 함수의 최상위 (at the top level) 에서 Hook를 호출해야 한다.
  • 컴포넌트가 render 될 때마다 동일한 순서로 Hook가 호출되는 것을 보장한다. ( 여러번 호출되도 Hook의 상태를 올바르게 유지할 수 있게 해준다)

ESLint 플러그인

  • eslint-plugin-react-hooks 라는 ESLint를 플러그인을 프로젝트에 추가할 수 있다.
npm install eslint-plugin-react-hooks --save-dev

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

규칙을 지키는것이 왜 중요한가?

  • 컴포넌트에서 State나 Effect Hook를 여러개 사용할 수 있다.
  • React는가 Hook의 호출되는 순서에 의존한다
// ------------
// 첫 번째 렌더링
// ------------
useState('Mary')           // 1. 'Mary'라는 name state 변수를 선언합니다.
useEffect(persistForm)     // 2. 폼 데이터를 저장하기 위한 effect를 추가합니다.
useState('Poppins')        // 3. 'Poppins'라는 surname state 변수를 선언합니다.
useEffect(updateTitle)     // 4. 제목을 업데이트하기 위한 effect를 추가합니다.

// -------------
// 두 번째 렌더링
// -------------
useState('Mary')           // 1. name state 변수를 읽습니다.(인자는 무시됩니다)
useEffect(persistForm)     // 2. 폼 데이터를 저장하기 위한 effect가 대체됩니다.
useState('Poppins')        // 3. surname state 변수를 읽습니다.(인자는 무시됩니다)
useEffect(updateTitle)     // 4. 제목을 업데이트하기 위한 effect가 대체됩니다.

// ...
  • Hook의 호출 순서가 렌더링 간에 동일하다면 React는 지역적인 state를 각 Hook에 연동시킨다.
// 🔴 조건문에 Hook을 사용함으로써 첫 번째 규칙을 깼습니다
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }
  • 위 처럼 Hook를 조건문 안에서 호출한다면 name ! == ' ' 조건은 첫 번째 렌더링에서 true이기 때문에 hook가 동작하지만 다음 렌더링에서 폼을 초기화하면 조건이 false가 되어 hook를 건너뛰기 때문에 Hook 호출순서가 달라진다.
useState('Mary')           // 1. name state 변수를 읽습니다. (인자는 무시됩니다)
// useEffect(persistForm)  // Hook를 건너뛰었습니다!
useState('Poppins')        // 2. (3이었던). surname state 변수를 읽는 데 실패했습니다.
useEffect(updateTitle)     // 3. (4였던). 제목을 업데이트하기 위한 effect가 대체되는 데 실패했습니다.
  • 이 때문에 Hook는 컴포넌트 최상위 (at the top level) 에서 호출되어야 한다.
useEffect(function persistForm() {
    // 컴포넌트 최상위에서 호출해주면서 더 이상 첫 번째 규칙을 어기지 않게 됬습니다.
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

'Web > React.js' 카테고리의 다른 글

Suspense를 사용하자  (0) 2021.12.14
[STUDY] 커스텀 Hooks  (0) 2021.03.27
[STUDY] Effect Hook 사용하기  (0) 2021.03.22
[STUDY] State Hook 사용하기  (0) 2021.03.21
[STUDY] Hook 개요  (0) 2021.03.19

댓글