React에서 폼 처리는 입력값 추적, 유효성 검사, 이벤트 처리 등 많은 요소가 복합적으로 작동해.
TypeScript를 사용하면 입력값과 이벤트의 타입을 명확하게 정의해서 안정성을 높일 수 있어.
import { useState } from 'react';
const ControlledInput = () => {
const [value, setValue] = useState<string>('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
return <input type="text" value={value} onChange={handleChange} />;
};
✅ 입력 요소에 value와 onChange를 함께 지정하면 controlled component가 돼.
타입스크립트에선
useState<string>()
,ChangeEvent<HTMLInputElement>
로 타입을 지정하면 오류를 줄일 수 있어.
select
, radio
의 타입화const GenderSelect = () => {
const [gender, setGender] = useState<'male' | 'female'>('male');
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setGender(e.target.value as 'male' | 'female');
};
return (
<select value={gender} onChange={handleChange}>
<option value="male">남자</option>
<option value="female">여자</option>
</select>
);
};
✅ select는 문자열만 반환하므로 as 단언문으로 타입을 좁히거나 e.target.value as const를 활용해줘야 안전해.
type FormData = {
email: string;
password: string;
};
const LoginForm = () => {
const [form, setForm] = useState<FormData>({
email: '',
password: '',
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
};
return (
<>
<input name="email" value={form.email} onChange={handleChange} />
<input
name="password"
type="password"
value={form.password}
onChange={handleChange}
/>
</>
);
};
✅ name 속성과 객체 key를 매핑할 때 form[name] 식 접근은 오류가 날 수 있어.
이럴 땐 객체 전체를 복사하면서 업데이트하는 게 가장 안전해.
const SubmitForm = () => {
const [email, setEmail] = useState('');
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
alert(`제출된 이메일: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">제출</button>
</form>
);
};
✅ FormEvent<HTMLFormElement> 타입은 submit 이벤트에 정확히 대응해.
.preventDefault()
로 브라우저의 기본 동작도 차단할 수 있어.