#How to add client-side validation with form actions?

1 messages · Page 1 of 1 (latest)

exotic sparrow
#

I have a form that uses server actions and form actions to handle its submission, how can I add client-side validation to my form and handle the form action as well?

nocturne wharfBOT
#

Hi @exotic sparrow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

For basic client-side form validation, you can use HTML validation attributes like required and type="email". These attributes provide immediate feedback to the user and help prevent invalid form submissions.

Here's an example of how you can use these attributes in your form:

<form action={formAction}>
 <label htmlFor="email">Email</label>
 <input type="text" id="email" name="email" required />
 {/* ... */}
</form>

For more advanced validation, you can use a schema validation library like Zod to validate the form fields before mutating the data. Here's an example of how you can use Zod for server-side validation:

import { z } from 'zod'
 
const schema = z.object({
 email: z.string({
 invalid_type_error: 'Invalid Email',
 }),
})
 
export default async function createUser(formData: FormData) {
 const validatedFields = schema.safeParse({
 email: formData.get('email'),
 })
 
 // Return early if the form data is invalid
 if (!validatedFields.success) {
 return {
 errors: validatedFields.error.flatten().fieldErrors,
 }
 }
 
 // Mutate data
}

Once the fields have been validated on the server, you can return a serializable object in your action and use the React useFormState hook to show a message to the user. Here's an example:

'use server'
 
export async function createUser(prevState: any, formData: FormData) {
 // ...
 return {
 message: 'Please enter a valid email',
 }
}

Then, you can pass your action to the useFormState hook and use the returned state to display an error message:

#
'use client'
 
import { useFormState } from 'react-dom'
import { createUser } from '@/app/actions'
 
const initialState = {
 message: '',
}
 
export function Signup() {
 const [state, formAction] = useFormState(createUser, initialState)
 
 return (
 <form action={formAction}>
 <label htmlFor="email">Email</label>
 <input type="text" id="email" name="email" required />
 {/* ... */}
 <p aria-live="polite" className="sr-only">
 {state?.message}
 </form>
 )
}

Remember to always ensure a user is also authorized to perform the action before mutating data.

For more information, you can refer to the following sources:


Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: