React 19 RC와 useActionState 훅 실험
배경
사내 어드민 페이지의 form 처리 로직이 복잡해지면서 리팩토링이 필요했다. 마침 React 19 RC가 공개되어 useActionState(구 useFormState)를 테스트해보기로 했다.
기존 코드의 문제
기존에는 useState, useEffect, try-catch를 조합해서 loading, error, success 상태를 모두 수동으로 관리했다.
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
await updateUser(formData);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
useActionState 적용
React 19의 useActionState는 이 패턴을 훅 하나로 처리한다.
const [state, submitAction, isPending] = useActionState(
async (prevState, formData: FormData) => {
try {
const result = await updateUser({
name: formData.get('name') as string,
});
return { success: true, message: '저장 완료' };
} catch (error) {
return { success: false, message: error.message };
}
},
{ success: false, message: '' }
);
return (
<form action={submitAction}>
<input name="name" />
<button disabled={isPending}>저장</button>
{state.message && <div>{state.message}</div>}
</form>
);
주의사항
- action prop에 전달하면 자동으로 FormData를 생성해준다
- isPending은 실제 async 함수 실행 시간만 추적한다
- 아직 RC라서 프로덕션 적용은 보류했다
결론
form 처리 보일러플레이트가 확실히 줄어들었다. 정식 릴리즈 후 점진적으로 마이그레이션 계획을 세울 예정이다.