Replies: 4 comments 5 replies
-
I've been thinking about this for a while: In my opinion, it's best to do both client-side and server-side validation. Client-side validation enhances the user experience, while server-side validation is necessary regardless (How to Think About Security in Next.js). I attempted to use React Hook Form (RHF) for the client side validation, but I couldn't find a smart way to incorporate RHF into Lee's example. The only solution I found was to run RHF's validation with {mode: 'onBlur'}. However, the user experience isn't great. I'm not quite sure why I would choose to use |
Beta Was this translation helpful? Give feedback.
-
I'm investigating this myself, but I still haven't found a good example that works for both client-side and server-side validation, and also, if JavaScript is enabled, not only validate on the client side but also, if the form is invalid, don't execute the server actions, and don't reload the page either. And if JavaScript is disabled, make server-side validations work and initialize the useForm hook with both the values and the errors. (With the errors I couldn't, even though the hook has the errors property, if I passed any value it would explode everything with very strange errors). |
Beta Was this translation helpful? Give feedback.
-
@zeekrey how about using 'setError()' from rhf on the client-side to incorporate the server-side errors into client-side form? In Server Action, use Zod to perform the server-side validation and return an object with ZodError validation errors
Then on client-side (in the component where you call the Server Action), read the returned errors and use the 'setError()' from react-hook-form to merge the server-side ZodError with client-side rhf's validation errors.
|
Beta Was this translation helpful? Give feedback.
-
this is my implementation with RHF + Zod for both Client + Server side validation with server actions : "use client";
....
const formSchema = z.object({
.....
});
const [loading, setLoading] = useState(false);
const form = useForm<ProductFormValues>({
resolver: zodResolver(formSchema),
defaultValues,
});
const clientAction = async (formData: FormData) => {
try {
// trigger client-side validation
form.trigger();
if (!form.formState.isValid) {
return;
}
setLoading(true);
const {
errors, // from zod validation from the server
message = "",
data, // result of successful mutation
} = await updateProduct(product.id.toString(), formData);
//Show toast with a success message
toast.custom(`... ${data.title} is Created 🚀`);
} catch (error: any) {
toast.error("Something went wrong.", JSON.strinfy(errors));
} finally {
setLoading(false);
}
};
...
<Form {...form}>
<form action={clientAction} className="w-full space-y-8">
<div className="gap-8 md:grid md:grid-cols-3">
...
const formSchema = z.object({
....
});
/**
** Creates a new product.
*
* @param {FormData} formData - The form data of the new product.
* @returns {Promise<Product>} A promise that resolves to the created product.
*/
export async function createProduct(formData: FormData) {
try {
const validatedFields = formSchema.safeParse({
...
});
// Return early if the form data is invalid
if (!validatedFields.success) {
return {
errors: validatedFields.error.flatten().fieldErrors,
};
}
const res = await axios.post(
`${API_URL}/products`,
validatedFields.data,
);
revalidatePath("/admin/products");
revalidatePath("/products");
return { message: "Create Product successfully", data: res.data };
} catch (error) {
console.error(`Failed to create product:`, error?.response?.data);
return {
errors: {
title: "There was an error with this title",
description: "There was an error with this description",
...
},
message: error?.response?.data,
};
}
} |
Beta Was this translation helpful? Give feedback.
-
Summary
Looking at this example https://github.com/vercel/next.js/tree/canary/examples/next-forms, a question about client-side validation came to my mind. Should there be additional client-side validation, or is server-side validation "enough"?
Currently, I largely use React Hook Forms. I was wondering if I could leave the React Hook Form code and client-side validation in place and add the server-side validation on top. But then I wondered how to inject the server-side validation errors into React Hook Form. 😅
Two questions:
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions