본문 바로가기
C.W.K.
Stream
Lesson 02 of 07 · published

React 훅 타입: 초기값과 상태 전이에서 추론 살리기

~10 min · frameworks, react, hooks

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"훅의 타입을 길게 외우기보다, 정확한 초기값과 상태 전이 함수를 건네."

useState의 추론 폭

useState(0)은 숫자 상태를, useState('ready')는 문자열 상태를 추론해. 처음 값이 null이지만 나중에 User가 들어간다면 useState<User | null>(null)처럼 전체 수명을 제네릭에 드러내야 해.

객체 상태는 초기 객체의 모양에 너무 묶이거나 넓어질 수 있어. 상태가 여러 단계라면 선택 필드를 한 객체에 쌓기보다 { status: 'loading' } | { status: 'ready', data: User } 같은 판별 합집합이 불가능한 조합을 줄여.

useReducer로 전이 규칙 모으기

reducer의 StateAction을 정확히 선언하면 useReducer가 dispatch까지 연결해 줘. action을 판별 합집합으로 만들고 switch에서 모두 처리하면 새 동작을 추가할 때 빠진 분기를 찾기 쉽지.

기본 분기에서 조용히 기존 상태를 반환하는 방식은 오타 action을 감출 수 있어. 외부 입력이 아닌 내부 action이라면 never 검사로 완전성을 확인하는 패턴을 고려해.

커스텀 훅의 공개 모양

커스텀 훅도 평범한 함수야. 여러 값을 반환할 때 위치 의미가 안정된 작은 쌍이면 튜플이 편하고, 필드가 늘거나 선택적으로 소비된다면 이름 있는 객체가 읽기 좋아. 튜플을 반환할 때 as const 또는 명시적 튜플 타입으로 배열처럼 넓어지는 것을 막아.

훅 안에서 any가 들어오면 상태와 콜백 전체로 퍼져. 소비 컴포넌트마다 단언을 붙이지 말고 API 응답이나 외부 라이브러리 같은 최초 경계로 돌아가 검증과 타입을 바로잡아.

훅 타입은 상태의 가능한 수명과 전이를 표현해야 해. 정확한 초기값, 판별 가능한 상태, 좁은 외부 경계가 긴 제네릭 주석보다 효과적이야.

Code

Hook — useState, useReducer, custom·tsx
import { useState, useReducer, useEffect } from 'react';

// useState — inference 가 흔한 case 처리.
function Counter() {
  const [count, setCount] = useState(0);          // number
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

// useState — nullable/union 초기에 명시 generic.
function UserProfile() {
  const [user, setUser] = useState<User | null>(null);
  // ...
  return null;
}

// useReducer — action 용 discriminated union.
type Action =
  | { type: 'increment' }
  | { type: 'decrement' }
  | { type: 'set'; value: number };

function reducer(state: number, action: Action): number {
  switch (action.type) {
    case 'increment': return state + 1;
    case 'decrement': return state - 1;
    case 'set': return action.value;
  }
}

function CounterAdvanced() {
  const [count, dispatch] = useReducer(reducer, 0);
  return (
    <button onClick={() => dispatch({ type: 'increment' })}>{count}</button>
  );
}

// Custom hook.
function useDelayed<T>(value: T, ms: number): T {
  const [delayed, setDelayed] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDelayed(value), ms);
    return () => clearTimeout(id);
  }, [value, ms]);
  return delayed;
}

External links

Exercise

초기 불리언 값과 토글 함수를 튜플로 반환하는 useToggle 훅을 작성해. 상세 내용 표시 컴포넌트에서 구조 분해한 두 값의 타입을 확인해.
Hint
내부 상태를 만들고 함수형 갱신으로 이전 값을 뒤집어. 반환 배열이 일반 배열로 넓어지지 않도록 튜플 타입을 명시하거나 as const를 사용해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.