useNexusFormAction
useNexusFormAction은 서버 액션을 HTML 폼 액션으로 간단하게 사용하기 위한 클라이언트 사이드 훅입니다. React의 표준 useFormState 훅을 기반으로 만들어졌으며, pending/success/error 상태와 생명주기 콜백을 추가로 제공합니다.
Import
import { useNexusFormAction } from 'next-nexus/client';핵심 개념 (Core Concepts)
언제 사용하나요?
HTML <form>을 점진적으로 향상시키고 싶을 때 이 훅을 사용하세요. 서버 액션을 통해 폼을 제출할 수 있게 해주며, 최소한의 클라이언트 사이드 자바스크립트로 훌륭한 사용자 경험을 제공합니다. Next.js에서 서버 액션으로 폼 제출을 처리하는 가장 권장되는 방법입니다.
동작 방식
서버 액션을 훅에 전달하면, <form action={formAction}> 속성에 직접 전달할 formAction 함수를 반환합니다. 이 훅은 pending 상태와 서버 액션에서 반환된 결과를 포함하여 폼의 상태를 관리합니다.
시그니처 (Signature)
파라미터 (Parameters)
serverAction:(formData: FormData) => Promise<TResult>— 폼 제출 시 실행될 서버 액션.FormData를 자동으로 받습니다.options?: 생명주기 콜백을 설정하는 선택적 객체.
반환 값 (Return Value)
다음을 포함하는 객체:
formAction:(payload: FormData) => void—<form>의action속성에 전달할 함수.isPending:booleanisSuccess:booleanisError:booleanresult:TResult | undefinederror:Error | nullreset:() => void
Options
onStart?:(formData: FormData) => void | Promise<void>onSuccess?:(result: TResult, formData: FormData) => void | Promise<void>onError?:(error: Error, formData: FormData) => void | Promise<void>onSettled?:(result?: TResult, error?: Error, formData: FormData) => void | Promise<void>
예제 (Example)
이 예제는 서버 액션을 사용하여 새 상품을 생성하는 간단한 폼을 보여줍니다. isPending 상태는 제출 중에 버튼을 비활성화하는 데 사용됩니다.
'use client'
import { useNexusFormAction } from 'next-nexus/client'
import { revalidateServerTags } from 'next-nexus'
import { revalidateClientTags } from 'next-nexus/client'
// 이 액션은 app/actions.ts와 같은 별도 파일에 있다고 가정합니다.
async function createProductAction(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// ... 상품을 생성하는 데이터베이스 로직
await revalidateServerTags(['products']);
return { ok: true, productName: name };
}
export default function ProductForm() {
const { formAction, isPending, isSuccess, result } = useNexusFormAction(createProductAction, {
onSuccess: () => {
revalidateClientTags(['products']);
}
});
return (
<form action={formAction}>
<input name="name" placeholder="상품명" required />
<button type="submit" disabled={isPending}>
{isPending ? '저장 중...' : '저장'}
</button>
{isSuccess && <div>상품 "{result?.productName}"이(가) 저장되었습니다!</div>}
</form>
);
}함께 보기