커스텀 훅은 useState, useEffect 같은 기본 훅을 조합해 공통 로직을 재사용하기 위한 기능이야.

타입스크립트와 함께 쓸 때는 입력값, 반환값의 타입 정의가 핵심이야.


📘 예제 61: 기본 커스텀 훅 구조

import { useState } from 'react';

const useCounter = () => {
  const [count, setCount] = useState(0);
  const increase = () => setCount((c) => c + 1);
  const decrease = () => setCount((c) => c - 1);

  return { count, increase, decrease };
};

✅ 커스텀 훅은 반드시 use로 시작해야 하고, 내부에 다른 훅이 포함되어야 해.

외부에서는 useCounter()처럼 간단히 사용 가능.


📘 예제 62: 상태 포함 커스텀 훅

const useToggle = (initialValue: boolean = false) => {
  const [value, setValue] = useState<boolean>(initialValue);
  const toggle = () => setValue((prev) => !prev);

  return { value, toggle };
};

✅ 상태를 포함하는 커스텀 훅에서는 useState와 초기값 타입을 명확히 설정.

이렇게 만들면 여러 UI 컴포넌트에서 쉽게 재사용 가능.


📘 예제 63: 입력 파라미터 타입화

type TimerOptions = {
  interval?: number;
};

const useTimer = ({ interval = 1000 }: TimerOptions) => {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => setSeconds((s) => s + 1), interval);
    return () => clearInterval(id);
  }, [interval]);

  return seconds;
};

✅ 매개변수를 객체 형태로 받고 기본값을 설정하면 확장성이 좋아지고, TypeScript에서 타입 정의도 간단해져.


📘 예제 64: 리턴값 타입 구조화

type UseInputReturn = {
  value: string;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  reset: () => void;
};

const useInput = (initial: string): UseInputReturn => {
  const [value, setValue] = useState(initial);

  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value);
  };

  const reset = () => setValue(initial);

  return { value, onChange, reset };
};

✅ 리턴값을 명확하게 객체 구조로 만들면 컴포넌트에서 구조 분해할 때 쓰기 쉬워.

타입도 UseInputReturn처럼 따로 분리하면 더 깔끔해.