Validated Server Action for useActionState
Hard · Server Actions
With React's useActionState(action, initialState), a form calls a Server Action as action(previousState, formData) and renders whatever state it returns: field errors, the values to put back in the inputs, or a success message. FormData only contains strings, so the action has to convert and validate them itself.
Implement the Server Action signup(prevState, formData) using SIGNUP_SCHEMA from the starter. Check the rules of each field in this order and keep only the first error per field:
- text / email: the value is formData.get(name) trimmed ("" when missing). Empty and required: "Required". Shorter than minLength: "Must be at least N characters". For email, not matching EMAIL_RE: "Enter a valid email".
- password: same, but never trimmed.
- number: the trimmed string. Empty is fine unless required. Not matching /^-?\d+$/: "Must be a whole number". Below min: "Must be at least N". Above max: "Must be at most N".
- checkbox: true only when the value is exactly "on" (what a checked box sends), otherwise false.
- multi: all values from formData.getAll(name). The first value that is not in options: "Unknown option: <value>". More than max values: "Choose at most N".
Every returned state has attempts = (prevState?.attempts ?? 0) + 1.
- If there are errors, return { status: "error", attempts, fieldErrors, values }. fieldErrors holds only the failing fields. values refills the form: trimmed name and email, age as the trimmed string, newsletter as a boolean, interests as an array. Never send the password back.
- Otherwise return { status: "success", attempts, message: "Welcome, <name>!" } with the trimmed name.
The driver runForm(submissions) is already written: each submission is a list of [key, value] pairs appended to a new FormData.