How to use react-hook-form with form action
Unanswered
Sun bear posted this in #help-forum
Sun bearOP
This code doesn't trigger any validation on submit
const FormSchema = z.object({
email: z
.string()
.min(1, { message: "." })
password: z
.string()
.min(4, { message: "." }),
});
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
email: "",
password: "",
},
});
const handleLogin = async (formData: FormData) => {
const email = formData.get("email") as string;
const password = formData.get("password") as string;
let user = await signIn(email, password);
if (isUser(user)) {
const { email, isSignedIn, error } = user;
if (!error.isError) {
setSession(user);
redirect("/dashboard");
}
}
};
<Form {...form}>
<form
action={(formData) => startTransition(() => handleLogin(formData))}
className="w-2/3 space-y-6"
>
<h1 className="text-4xl text-center font-semibold">Login</h1>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type="password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full"
disabled={isPending}
>
Login
{isPending ? (
<ReloadIcon className="mx-2 h-4 w-4 animate-spin" />
) : null}
</Button>
</form>
</Form>12 Replies
Sun bearOP
Sun bearOP
Any ideas where the error might be?
Barbary Lion
have you tried it without
startTransition ?action={handleLogin}
Sun bearOP
Nope, it didn't validate. It needs
form.handleSubmit But i am unable to figure out how to do it with actions?Also I am new to nextjs. Is it even worth using
action={}? can't I just call the server action inside a handleSubmit? why is everyone using action?Barbary Lion
yeah so ive seen nothing but issues and confusion with server actions and wouldnt recommend them. I'd use more common stable patterns that have been around for a while. Heres an example with react-hook-form
<Form {...form}>
<form
onSubmit={form.handleSubmit(handleSubmit)}
className="space-y-4"
>
<FormField
disabled={isLoading}
control={form.control}
name="agencyLogo"
render={({ field }) => (
<FormItem>
<FormLabel>Agency Logo</FormLabel>
<FormControl>
<FileUpload
apiEndpoint="agencyLogo"
onChange={field.onChange}
value={field.value}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/> const handleSubmit = async (values: z.infer<typeof FormSchema>) => {
try {
let newUserData
let custId
if (!data?.id) {
const bodyData = {
email: values.companyEmail,
name: values.name,
shipping: {
address: {
city: values.city,
country: values.country,
line1: values.address,
postal_code: values.zipCode,
state: values.zipCode,
},
name: values.name,
},
address: {
city: values.city,
country: values.country,
line1: values.address,
postal_code: values.zipCode,
state: values.zipCode,
},
}
const customerResponse = await fetch('/api/stripe/create-customer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(bodyData),
})
const customerData: { customerId: string } =
await customerResponse.json()
custId = customerData.customerId
} const form = useForm<z.infer<typeof FormSchema>>({
mode: 'onChange',
resolver: zodResolver(FormSchema),
defaultValues: {
name: data?.name,
companyEmail: data?.companyEmail,
companyPhone: data?.companyPhone,
whiteLabel: data?.whiteLabel || false,
address: data?.address,
city: data?.city,
zipCode: data?.zipCode,
state: data?.state,
country: data?.country,
agencyLogo: data?.agencyLogo,
},
})Sun bearOP
Thanks!
Barbary Lion
No problem!