useActionState
useActionState manages form state across submissions, preserving input after validation errors.
Example: PostForm
From app/dashboard/_components/PostForm.tsx:
'use client';
import { useActionState } from 'react';
export function PostForm({ action, defaultValues, redirectTo }) {
const router = useRouter();
const [state, formAction] = useActionState(async (_prev, formData) => {
const result = await action(formData);
if (result.success) {
router.push(redirectTo);
return _prev;
}
return result.formData ?? _prev;
}, defaultValues);
return (
<form action={formAction}>
<input name="title" defaultValue={state.title} />
<SubmitButton>Save</SubmitButton>
</form>
);
}On error, the form data is returned so fields keep their values.
Reusing for Create and Edit
// Create
<PostForm action={createPost} defaultValues={{ title: '' }} />
// Edit - use .bind() to apply the slug
<PostForm action={updatePost.bind(null, post.slug)} defaultValues={post} />