[멋쟁이사자처럼 부트캠프 프론트엔드 14기/REACT] Rules of React Hooks

minji·2025년 8월 29일
post-thumbnail

"사용하더라도 규칙을 알고 사용하자!"

React Hook은 자바스크립트 함수로 정의는 되지만, 호출 위치에 제약이 있는 특별한 유형의 재사용 가능한 UI 로직이다.

훅을 호출하기 좋은 위치는 다음과 같다.

  • 리액트 함수 컴포넌트에서 호출하되, 본문 최상위 레벨에서 호출하기
  • 커스텀 훅 에서 호출하되, 본문 최상위 레벨에서 호출하기

커스텀 훅 vs. 빌트인(내장) 훅

  • 빌트인(내장) 훅
    - useState, useEffect, useRef 등
  • 커스텀 훅
    - 빌트인 훅을 포함하여 재사용 가능한 로직으로 개발자가 직접 정의한 함수
    - 컴포넌트 리렌더링때마다 작동함 → 그래서 순순해야해!

훅의 생김새를 보면 일반 함수와 크게 다른 점은 없어보인다.
그렇다면 어떤걸 Hook 이라고 하는걸까?

  • 일반 함수 vs. 훅 함수 구분 → use 로 시작하는지의 여부에 따라 결정됨 (훅 함수는 use 로 시작한다.)
  • 함수형 컴포넌트 vs. 사용자 정의 훅 (커스텀 훅) → 대문자로 시작하는지의 여부에 따라 결정됨 (파스칼 케이스 / 훅 함수는 대문자로 시작한다.)

훅의 규칙(Rules of React Hooks)

1️⃣ 함수형 컴포넌트 내에서만 사용가능하다.

| 리액트 훅은 함수 컴포넌트 본문에서만 사용할 수 있다.

일반 함수, 클래스 컴포넌트, 컴포넌트 외부 에서는 사용할 수 없다. ❌

아래 예시를 통해 사용가능한 경우와 불가한 경우를 비교해보자.

// 사용가능한 경우 - 함수 컴포넌트 내부사용 (본문 최상단 배치 권장)
import { useState, useEffect } from 'react'

export default function App() {

	const [count, setCount] = useState(0) // ✅
	useEffect(() => { document.title = count }, [count]) // ✅
	
	return (...)
}

// 사용불가한 경우
// 1. 클래스 컴포넌트에서 사용
import { Component, useState, useEffect } from 'react'

export default class App extends Component {
  render() {
  
  	const [count, setCount] = useState(0) // ❌
		useEffect(() => { document.title = count }, [count]) // ❌
	
		return (...)
  } 
}

// 2. 일반 함수에서 사용
export function normalFunction() {
	const [count, setCount] = useState(0) // ❌
	useEffect(() => { document.title = count }, [count]) // ❌
	
	// ...
}

단, 여러 훅을 조합하여 만든 함수인 커스텀 훅(사용자 정의 훅) 내부에서는 사용가능하다.

import { useState, useEffect } from 'react'

function useCustomHook() {
  const [count, setCount] = useState(0) // ✅
	useEffect(() => { document.title = count }, [count]) // ✅
}

2️⃣ 항상 같은 순서, 같은 수 로 호출되어야 한다.

| 항상 같은 순서, 같은 수 로 훅 함수가 실행되어야 한다.

그렇기때문에 조건문, 반복문, 중첩 함수, try / catch / finally 블록 내부에서 사용하면 안된다.
조건을 설정해줘야 하는 경우에는 훅 함수 내부에 조건문 또는 반복문을 작성해야 한다.

훅 함수를 조건문 이나 반복문 내부에 넣으면 안되는 이유는 뭘까?
→ 조건부로 실행될 경우, 렌더링때마다 실행 순서 및 갯수가 달라진다. 그로인해, 내부적 상태관리 혼란발생 → 오류 발생 및 렌더링 깨짐현상 발생

Hook 을 사용하면 안되는 경우를 정리해보면 다음과 같다.

  • ❌ 조건문 이나 반복문 내부에서 호출하지 말기
  • ❌ 조건부 return 문 이후에 호출하지 말기
  • ❌ 이벤트 핸들러 에서 호출하지 말기
  • ❌ 클래스 컴포넌트에서 호출하지 말기
  • ❌ useMemo, useRedeucer, useEffect 에 전달된 함수 내부에서 호출하지 말기
  • ❌ try / catch / finally 블록내부에서 호출하지 말기
    ⇒ 위 규칙을 어길 경우 오류가 발생하므로 유의하여 사용하도록 하자!

이렇게 규칙을 정하고 숙지하더라도 누구나 실수를 할 수 있다.
실수 를 예방하기 위해 eslint-plugin-react-hooks 플러그인을 사용할 수 있으며, 해당 설정은 eslint.config.js 파일 내에서 할 수 있다.
간략하게나마 관련된 환경설정의 내용을 살펴보면 다음과 같다.

// eslint.config.js 파일 내용(플러그인)

  // React의 JSX 런타임(automatic) 설정
  pluginReact.configs.flat['jsx-runtime'],
  // JSX 접근성(Accessibility) 권장 규칙 적용
  pluginJsxA11y.flatConfigs.recommended,
  // React Hooks의 올바른 사용을 위한 권장 규칙 적용
  pluginReactHooks.configs['recommended-latest'],
  // Prettier와 ESLint 충돌 방지 및 Prettier 포맷팅 규칙 적용
  pluginPrettierRecommand,

  {
    rules: {
      // 정의되지 않은 변수 사용 금지
      'no-undef': 'error',

      // var 사용 금지
      // - ES6+ let/const 사용 강제
      // - 호이스팅 문제 및 스코프 혼란 방지
      'no-var': 'error',
      ...
    }

⚠️ 참고 및 주의사항

  • 컴포넌트 안에 또다른 컴포넌트를 호출하는 것은 안되는 일이다!!!!! ❌
profile
FE Developer .mjs

0개의 댓글