커스텀 훅은 useState
, useEffect
같은 기본 훅을 조합해 공통 로직을 재사용하기 위한 기능이야.
타입스크립트와 함께 쓸 때는 입력값, 반환값의 타입 정의가 핵심이야.
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()
처럼 간단히 사용 가능.
const useToggle = (initialValue: boolean = false) => {
const [value, setValue] = useState<boolean>(initialValue);
const toggle = () => setValue((prev) => !prev);
return { value, toggle };
};
✅ 상태를 포함하는 커스텀 훅에서는 useState와 초기값 타입을 명확히 설정.
이렇게 만들면 여러 UI 컴포넌트에서 쉽게 재사용 가능.
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에서 타입 정의도 간단해져.
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
처럼 따로 분리하면 더 깔끔해.