useFormStatus는 React에서 폼의 제출 상태를 관리하는 훅입니다. 이 훅은 폼의 현재 상태에 대한 정보를 제공하여 사용자 인터페이스를 동적으로 업데이트할 수 있게 해줍니다
'use client';
import { useFormStatus } from "react-dom";
import { submitForm } from "./actions.js";
function Submit() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "제출 중..." : "제출"}
</button>
);
}
function Form({ action }) {
return (
<form action={action}>
<Submit />
</form>
);
}
export default function App() {
return <Form action={submitForm} />;
}
useFormStatus를 사용하면 다음과 같은 이점이 있습니다
useActionState는 폼 액션의 결과를 기반으로 state를 업데이트할 수 있도록 제공하는 Hook 입니다.
const [state, formAction] = useActionState(action, initialState);
🟢 fn
form이 제출 되었을 때 실행되는 함수이다. 함수가 실행될 때, 첫 번째 인수로 폼의 이전 state를 전달합니다. state는 초기에 전달한 initialState이고, 이후에는 이전 실행의 반환값입니다. 그 후 일반적으로 폼 액션에 전달하는 인수들이 이어집니다.
🟢 initialState
초기 state로 설정하고자 하는 값으로, 직렬화 할 수 있는 값일 수 있습니다. 액션이 처음 호출된 후에는 이 인수를 무시합니다.
✍️ 반환값
useActionState는 다음 3가지 값들이 포함된 배열을 반환합니다.
- 현재 state입니다. 첫 번째 렌더링에서는 전달한 initialState와 일치합니다. 액션이 실행된 이후에는 액션에서 반환한 값과 일치합니다.
- form 컴포넌트의 action prop에 전달하거나 폼 내부 button 컴포넌트의 formAction prop에 전달할 수 있는 새로운 액션입니다.
- 대기 중인 전환(Pending Transition)이 있는지 여부를 알려주는 isPending 플래그입니다.
"use client"
import { useActionState } from 'react';
import { action } from './actions.ts';
function MyComponent() {
const [state, formAction] = useActionState(action, null);
// ...
return (
<form action={formAction}>
{state?.errors ?? []}
</form>
);
}
필드가 서버에서 검증되면 작업에서 직렬화 가능한 객체를 반환하고 React useActionState후크를 사용하여 사용자에게 메시지를 표시할 수 있습니다.
'use server'
// action.ts
import { redirect } from 'next/navigation'
export async function createUser(prevState: any, formData: FormData) {
const res = await fetch('https://...')
const json = await res.json()
if (!res.ok) {
return { message: 'Please enter a valid email' }
}
redirect('/dashboard')
}
해당 작업을 후크에 전달 useActionState하고 반환된 내용을 사용하여 state오류 메시지를 표시할 수 있습니다.
'use client'
import { useActionState } from 'react'
import { createUser } from '@/app/actions'
const initialState = {
message: '',
}
export function Signup() {
const [state, formAction, pending] = useActionState(createUser, initialState)
return (
<form action={formAction}>
<label htmlFor="email">Email</label>
<input type="text" id="email" name="email" required />
{/* ... */}
<p aria-live="polite">{state?.message}</p>
<button disabled={pending}>Sign up</button>
</form>
)
}