TSX
Public
React Form Validation with useActionState
Manage form validation, submission status, and server-style action results with React useActionState.
#react
#hooks
#form
#validation
TSX
'use client';
import { useActionState } from 'react';
type FormState = {
message: string;
errors: {
email?: string;
};
};
const initialState: FormState = {
message: '',
errors: {},
};
async function subscribe(
previousState: FormState,
formData: FormData,
): Promise<FormState> {
const email = String(formData.get('email') ?? '').trim();
if (!email.includes('@')) {
return {
message: '',
errors: { email: 'Enter a valid email address.' },
};
}
await saveSubscriber(email);
return {
message: 'Subscription saved.',
errors: {},
};
}
export function NewsletterForm() {
const [state, formAction, isPending] = useActionState(
subscribe,
initialState,
);
return (
<form action={formAction}>
<label htmlFor="newsletter-email">Email</label>
<input
id="newsletter-email"
name="email"
type="email"
aria-describedby="newsletter-feedback"
required
/>
<button type="submit" disabled={isPending}>
{isPending ? 'Saving…' : 'Subscribe'}
</button>
<p id="newsletter-feedback" aria-live="polite">
{state.errors.email ?? state.message}
</p>
</form>
);
}
async function saveSubscriber(email: string) {
console.log('Save subscriber:', email);
}