
React Hook은 자바스크립트 함수로 정의는 되지만, 호출 위치에 제약이 있는 특별한 유형의 재사용 가능한 UI 로직이다.
훅을 호출하기 좋은 위치는 다음과 같다.
함수 컴포넌트에서 호출하되, 본문 최상위 레벨에서 호출하기커스텀 훅 에서 호출하되, 본문 최상위 레벨에서 호출하기커스텀 훅 vs. 빌트인(내장) 훅
- 빌트인(내장) 훅
-useState,useEffect,useRef등- 커스텀 훅
- 빌트인 훅을 포함하여 재사용 가능한 로직으로 개발자가 직접 정의한 함수
- 컴포넌트 리렌더링때마다 작동함 → 그래서 순순해야해!
훅의 생김새를 보면 일반 함수와 크게 다른 점은 없어보인다.
그렇다면 어떤걸 Hook 이라고 하는걸까?
일반 함수 vs. 훅 함수 구분 → use 로 시작하는지의 여부에 따라 결정됨 (훅 함수는 use 로 시작한다.)함수형 컴포넌트 vs. 사용자 정의 훅 (커스텀 훅) → 대문자로 시작하는지의 여부에 따라 결정됨 (파스칼 케이스 / 훅 함수는 대문자로 시작한다.)함수형 컴포넌트 내에서만 사용가능하다.| 리액트 훅은 함수 컴포넌트 본문에서만 사용할 수 있다.
일반 함수, 클래스 컴포넌트, 컴포넌트 외부 에서는 사용할 수 없다. ❌
아래 예시를 통해 사용가능한 경우와 불가한 경우를 비교해보자.
// 사용가능한 경우 - 함수 컴포넌트 내부사용 (본문 최상단 배치 권장)
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]) // ✅
}
순서, 같은 수 로 호출되어야 한다.| 항상 같은 순서, 같은 수 로 훅 함수가 실행되어야 한다.
그렇기때문에 조건문, 반복문, 중첩 함수, 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',
...
}
⚠️ 참고 및 주의사항
- 컴포넌트 안에 또다른 컴포넌트를 호출하는 것은 안되는 일이다!!!!! ❌