프로젝트 생성
npm create vite@latest my-app -- --template react-ts
컴포넌트 Props 타입 정의
// interface 방식 (권장)
interface ButtonProps {
label: string
variant?: 'primary' | 'secondary' | 'danger'
disabled?: boolean
onClick: () => void
}
function Button({ label, variant = 'primary', disabled = false, onClick }: ButtonProps) {
return (
<button
className={`btn btn-${variant}`}
disabled={disabled}
onClick={onClick}
>
{label}
</button>
)
}
children 타입
import { ReactNode, FC } from 'react'
interface CardProps {
title: string
children: ReactNode
}
const Card: FC<CardProps> = ({ title, children }) => (
<div className="card">
<h2>{title}</h2>
{children}
</div>
)
이벤트 핸들러 타입
function Form() {
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
const form = e.currentTarget
const data = new FormData(form)
}
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
console.log(e.target.value)
}
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
console.log(e.currentTarget.id)
}
return (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} />
<button id="submit" onClick={handleClick}>제출</button>
</form>
)
}
useState 타입
const [count, setCount] = useState<number>(0)
const [user, setUser] = useState<User | null>(null)
const [items, setItems] = useState<string[]>([])
// 초기값으로 타입 추론 가능한 경우 생략 가능
const [name, setName] = useState('') // string으로 자동 추론
useRef 타입
// DOM 참조
const inputRef = useRef<HTMLInputElement>(null)
// 값 저장 (렌더링 없이)
const timerRef = useRef<ReturnType<typeof setTimeout>>(null)
제네릭 컴포넌트
interface ListProps<T> {
items: T[]
renderItem: (item: T) => ReactNode
keyExtractor: (item: T) => string
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map(item => (
<li key={keyExtractor(item)}>{renderItem(item)}</li>
))}
</ul>
)
}
// 사용
<List
items={users}
renderItem={user => <span>{user.name}</span>}
keyExtractor={user => user.id}
/>
API 응답 타입
// types/api.ts
export interface ApiResponse<T> {
data: T
message: string
success: boolean
}
export interface User {
id: number
name: string
email: string
}
// 사용
async function fetchUser(id: number): Promise<ApiResponse<User>> {
const res = await fetch(`/api/users/${id}`)
return res.json()
}