Rules of Hooks[React]

SnowCat·2023년 1월 18일
0

React - Hooks

목록 보기
4/7
post-thumbnail

※ 공식문서를 읽고 정리한 글입니다.

Hook을 소개하면서 컴포넌트 최상위에서만 Hook을 호출할 것, React함수와 Custom Hook에서만 Hook을 호출할 것 이라는 2가지 원칙을 소개했었다. React함수와 Custom Hook에서만 Hook을 호출해야 하는 것은 당연해 보이지만, 컴포넌트 최상위에서만 Hook을 호출해야 하는 이유에 대해서는 잘 납득이 되지 않는다. 공식문서에 이와 관련된 설명이 나와있다.

최상위 레벨에서만 Hook을 호출해야하는 이유

function Form() {
  // 1. name이라는 state 변수를 사용하세요.
  const [name, setName] = useState('Mary');

  // 2. Effect를 사용해 폼 데이터를 저장하세요.
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  // 3. surname이라는 state 변수를 사용하세요.
  const [surname, setSurname] = useState('Poppins');

  // 4. Effect를 사용해서 제목을 업데이트합니다.
  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
}
  • 예제처럼 state, effect hook을 여러개 사용하는 경우 리액트는 hook이 호출되는 순서에 의존해 어떤 useState, useEffect 인지를 알 수 있다
  • 조건문 안에 persistForm이 들어간 useEffect를 사용한 경우를 생각해보자
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }
  • 처음 상황에서는 초기값이 ""이 아니기 때문에 hook은 동작할 것이다. 그렇다면 만약 name === ""인 상황이 된다면 어떻게 될까?
  • 처음의 useState는 동작하지만, 두번째 hook(useState('Poppins'))에서는 persistForm effect가 나올 것이라 예측했지만, 다른 hook 호출이 들어와 리액트는 무엇을 반환할지 모르는 상황이 발생하게 됨
  • 마지막 hook 역시도 useState('Poppins') 대신에 updateTitle effect 가 들어오기 때문에 문제가 발생함
  • 따라서 오류를 사전에 방지하기 위해 컴포넌트의 최상위 레벨에서만 hook이 호출되어야함
useEffect(function persistForm() {
    // 조건문이 필요하면 useEffect 안에다 집어넣을것
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });
  • 앞선 예문과 같은 코드를 작성하고 싶으면 useEffect안에 조건문을 넣어야 함

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
  }
}
  • eslint-plugin-react-hooks 플러그인을 사용하면 규칙 위반 여부를 확인할 수 있음
    Create React App에 기본적으로 포함됨

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

profile
냐아아아아아아아아앙

0개의 댓글