IT 엘도라도 로고
IT 엘도라도
황금

React 공식 문서 요약 - Hook 규칙

2020-09-12 15:56

React 공식 문서 요약 - Hook 규칙

💡
React 공식 문서를 꼼꼼히 읽으면서 개인적으로 요약한 내용입니다. 잘못된 내용이 있다면 지적 부탁드립니다.
 

1. 컴포넌트의 최상위(Top Level)에서만 Hook을 호출해야 한다.

반복문, 조건문, 혹은 중첩된 함수 내에서 Hook을 호출하면 안 된다. 대신 React 함수형 컴포넌트의 최상위에서만 호출해야 한다. 이 규칙을 따르면 해당 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 여러 개의 Hook이 호출되는 것을 보장할 수 있다. 이는 React가 여러 개의 Hook이 호출되는 경우에도 각 Hook의 상태를 렌더링 간에 제대로 유지할 수 있도록 한다. 이에 대해서는 아래에서 자세히 설명한다.
 

2. 오직 React 함수 내에서 Hook을 호출해야 한다.

일반적인 JavaScript 함수 내에서 Hook을 호출하면 안 된다. 대신 React 함수형 컴포넌트 안에서 호출하거나, 직접 만든 커스텀 Hook 안에서만 호출하도록 하자. 커스텀 Hook과 관련한 자세한 내용은 '나만의 Hook 만들기' 포스팅을 참고하자. 이 규칙을 따르면 해당 컴포넌트의 상태와 관련한 모든 로직들을 소스 코드상에서 명확하게 보이도록 할 수 있다.
 

3. ESLint 플러그인 (eslint-plugin-react-hooks 패키지)

Hook을 사용할 때 위와 같은 두 가지의 규칙을 반드시 지키도록 강제하고 싶다면 ESLint 플러그인을 프로젝트에 추가하자. npm 혹은 yarn으로 eslint-plugin-react-hooks 패키지를 설치하고 ESLint 설정 파일을 다음과 같이 구성하면 된다. 참고로 create-react-app으로 만들어진 프로젝트에는 이 플러그인이 기본적으로 설정되어 있으므로 추가적인 설정이 필요하지 않다. 그리고 react-hooks/exhaustive-deps 설정은 앞선 포스팅에서 설명했듯이 useEffect() 함수를 사용할 때 의존성 배열을 올바르게 지정할 수 있도록 돕는 설정이다.
 

4. React는 어떤 상태가 어떤 Hook에 대응하는지 어떻게 알 수 있을까?

앞서 설명했듯 한 컴포넌트에서도 Hook을 여러 번 호출할 수 있다. 바로 위 예시처럼 말이다. 그렇다면 React는 어떤 상태가 어떤 Hook 호출에 대응하는지 어떻게 알 수 있을까? 즉, 각각의 Hook 호출이 기억되어 있는 이전의 Hook 상태들 중 어떤 상태를 참조해야 하는지 어떻게 알 수 있을까? 정답은 바로 Hook 호출의 순서이다. 즉, 호출의 순서대로 각각의 Hook 호출이 무엇인지 식별하는 것이다. 위 예시의 경우 매 렌더링마다 Hook 호출의 순서가 항상 같기 때문에 올바르게 동작한다. 다음 그림을 보자. Hook의 호출 순서가 매 렌더링마다 동일하다면 React는 지역적으로 기억해둔 상태들을 각각 알맞은 Hook에 대응시킬 수 있다.
그렇다면 Hook을 조건문 안에서 호출하면 어떻게 될까? 그러면 조건이 만족되지 않을 때는 해당 Hook이 호출되지 않으므로 이전 렌더링 때와는 Hook 호출 순서가 달라지게 된다. 다음 예시처럼 말이다. 원래 호출되던 useEffect(persistForm)이 호출되지 않았다.
이렇게 되면 React는 각각의 Hook 호출을 잘못 해석하게 된다. useState('Poppins') 호출의 경우 두 번째 호출된 Hook이기 때문에 이전 렌더링에서의 useEffect(persistForm) 호출에 대응되는 것으로 기대할 것이다. 그러나 결과적으로 그렇지 않고, 과거 useEffect(persistForm) 호출에 의해서는 상태 변수가 특별히 저장되지 않았기 때문에 useState('Poppins') 호출을 통해 저장되어 있는 상태 변수를 읽어오려 할 때 문제가 발생한다. 이때부터 Hook의 호출 순서는 하나씩 밀려서 전체적으로 버그를 만들게 된다. 이것이 컴포넌트의 최상위에서만 Hook을 호출해야 하는 진짜 이유이다. 만약 조건부로 이펙트를 수행하고 싶다면 effect 함수 내에 조건문을 넣자. 제공된 lint 플러그인을 잘 사용한다면 이러한 문제들은 전혀 걱정할 필요가 없을 것이다.
말풍선
댓글 0
좋아요 0
    아직 작성된 댓글이 없어요.
사용자