Rules of Hooks 가 엄격했던 건 reconciler 가 그게 필요했기 때문. React 19 의 use() 는 깨지지 않고 휘게 설계된 첫 hook. 어떤 규칙이 여전히 적용되고 어떤 규칙이 정확히 적용 안 되는지 아는 게 이 레슨의 요점.
클래식 두 규칙
- Hook 을 상단에서 호출. 조건 안 아님, 루프 안 아님, nested 함수 안 아님. Hook 이 매 render 같은 순서로 돌아야.
- Hook 을 React 함수에서 호출. 함수 컴포넌트 또는 커스텀 hook (이름이
use로 시작하는 함수) — 평범한 이벤트 핸들러나 유틸 함수에서 절대 아님.
이유: React 가 hook state 를 호출 순서로 추적. 본인 함수의 첫 hook useState(0) 가 이 컴포넌트 인스턴스에 영구적으로 '슬롯 0'. 조건이 hook 스킵하면 다음 render 가 다른 슬롯 매핑 봄 — 한 hook 의 state 가 다른 hook 으로 들어감. 시스템 전체가 조용히 깨짐.
use() 가 뭐
Promise 또는 Context 의 값을 인라인으로 읽는 React 19 hook. Context 넘기면 useContext 처럼 보임 (같이 동작), 다만 돌파구는 조건부 + 루프 안 에서 호출 가능하다는 것.
use() 가 특별한 이유
React 가 재설계되어 use() 의 호출 지점이 reconciler 에 안 중요. Suspense 를 resume 메커니즘으로 사용: use() 가 pending promise 만나면 React 가 컴포넌트 unwind 하고 promise resolve 시 재실행. 다른 hook 들의 동력인 '슬롯 추적' 이 적용 안 됨.
그래서 다음이 가능:
if (someCondition) {
const data = use(somePromise); // OK!
}
또는:
for (const promise of promises) {
const value = use(promise); // OK!
}
Trade-off
use() 는 위에 Suspense 경계 필요 (promise 용) + 호출 컴포넌트가 promise resolve 시 처음부터 재실행. 그 재실행이 비용. 대부분 데이터 페칭엔 승리 — 코드가 위에서 아래로 읽히고 Suspense 가 로딩 상태 선언적으로 처리. Track 5 에서 운동.
다른 hook 들은 여전히 규칙 따름. useState, useEffect, useRef, useContext, useReducer, 커스텀 hook — 다 여전히 상단에서 무조건 호출. 이 레슨 읽고 hook 을 조건 안에 숨기기 시작하지 마. use() 만 완화야.