I need to run some server actions on a client component because the shadcn/ui <Form>
component requires it. I am referencing docs from shadcn/ui and Lucia. shadcn/ui uses react-hook-form and zod.
Here's my code:
'use client'
// imports
const registerFormSchema = // zod schema
export default function Register() {
const form = useForm<z.infer<typeof registerFormSchema>>({
resolver: zodResolver(registerFormSchema)
})
return (
<Form {...form}>
<form onSubmit={register}>
<CardHeader>
<CardTitle>Register</CardTitle>
</CardHeader>
<CardContent className={"formContent"}>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem className={"formItem"}>
<FormLabel>Name</FormLabel>
<FormControl>
<Input type={"name"} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
// other form fields (email, password)
</CardContent>
<CardFooter className={"flex justify-between"}>
// buttons
</CardFooter>
</form>
</Form>
);
}
async function register(values: z.infer<typeof registerFormSchema>): Promise<ActionResult> {
'use server';
const result = registerFormSchema.safeParse(values);
if (!result.success) {
return { error: result.error.message }
}
const user = prisma.user.create(
{
data: {
name: values.name,
email: values.email,
password: values.password // dw ill hash it later
}
}
)
user.then(async (value) => {
const session = await lucia.createSession(value.id, {});
const sessionCookie = lucia.createSessionCookie(session.id);
cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
})
return redirect("/dashboard");
}
With 'use client'
at the top: You're importing a component that needs next/headers. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.
Without 'use client'
at the top: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it.
I also tried putting the register
function in another file, but that broke React hook rules.
This is not my first time running into large roadblocks with react-hook-forms and I'm pretty sure I'm missing something fundamental to do with react forms or just Next.js in general.
<form onSubmit={form.handleSubmit((value) => register(value))}>
instead of
<form onSubmit={register}>