Reputation: 11
I am trying to call the signup function defined my actions.ts (a server action) from a form on client side but I face the same error:
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.
import { lucia } from "@/auth";
import prisma from "@/lib/prisma";
import { signUpSchema, SignUpValues } from "@/lib/validation";
import { hash } from "@node-rs/argon2";
import { generateIdFromEntropySize } from "lucia";
import { isRedirectError } from "next/dist/client/components/redirect";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
export async function signUp(
credentials: SignUpValues
): Promise<{ error: string }> {
try {
const { username, email, password } = signUpSchema.parse(credentials);
const passwordHash = await hash(password, {
// recommended minimum parameters
memoryCost: 19456,
timeCost: 2,
outputLen: 32,
parallelism: 1
});
const userId = generateIdFromEntropySize(10); // 16 characters long
const existingUsername = await prisma.user.findFirst({
where:{
username:{
equals: username,
mode: "insensitive"
}
}
});
if (existingUsername){
return {error: "Username already taken"}
}
const existingEmail = await prisma.user.findFirst({
where:{
username:{
equals: email,
mode: "insensitive"
}
}
});
if (existingEmail){
return {error: "Email already taken"}
}
await prisma.user.create({
data:{
id: userId,
username: username,
displayName: username,
email: email,
passwordHash: passwordHash
}
})
const session = await lucia.createSession(userId, {});
const sessionCookie = lucia.createSessionCookie(session.id);
cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
return redirect("/");
} catch (error) {
if (isRedirectError(error)) throw error;
console.log(error);
return{
error: "Something went wrong. Please try again"
}
}
}
I am calling it from SignupForm.tsx (that I will later call in my page.tsx)
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client";
// import LoadingButton from "@/components/LoadingButton";
// import { PasswordInput } from "@/components/PasswordInput";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { signUpSchema, SignUpValues } from "@/lib/validation";
import { zodResolver } from "@hookform/resolvers/zod";
import { useState, useTransition } from "react";
import { useForm } from "react-hook-form";
import { signUp } from "./actions";
import { Button } from "@/components/ui/button";
export default function SignUpForm() {
const [error, setError] = useState<string>();
const [isPending, startTransition] = useTransition();
const form = useForm<SignUpValues>({
resolver: zodResolver(signUpSchema),
defaultValues: {
email: "",
username: "",
password: "",
},
});
async function onSubmit(values: SignUpValues) {
setError(undefined);
startTransition(async () => {
const { error } = await signUp(values);
if (error) setError(error);
});
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-3">
{error && <p className="text-center text-destructive">{error}</p>}
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Username" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="Email" type="email" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input placeholder="Password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full">
Create account
</Button>
</form>
</Form>
);
}
I don't understand where is the problem since I have already done things similar and it's the first time I faced this error
Upvotes: 0
Views: 52