Reputation: 93
I was writing a website with signIn and signOut function from next-auth/react. But sometimes when I sign out, error showing TypeError: Response body object should not be disturbed or locked
shows on the terminal. Although it sometimes still signOut properly, but other times it just redirect to the main page and I have to click the signOut button again to signOut. I guess the problem occurs in how I handle signIn and here's my code:
const handleSubmit = async(e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const result=await signIn("credentials", {
email,
password,
callbackUrl: `${publicEnv.NEXT_PUBLIC_BASE_URL}/AboutMe`,
redirect:false,
});
if((result)&&(result.error==="CredentialsSignin")){
toast({
variant: "destructive",
description: "輸入的帳號不存在或有誤,請再次輸入",
});
}
else if(result&&result.error==="CallbackRouteError"){
toast({
variant: "destructive",
description: "輸入的密碼不正確,請再次輸入",
});
}
else if (result && !result.error) {
router.push(`${publicEnv.NEXT_PUBLIC_BASE_URL}/AboutMe`);
router.refresh();
setOpen(false);
}
};
And here's my CredentialsProvider.ts
:
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcryptjs";
import { desc, eq } from "drizzle-orm";
import { db } from "@/db";
import { experiencesTable, usersTable } from "@/db/schema";
import { authSchema } from "@/validators/auth";
export default CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "text" },
username: { label: "Userame", type: "text", optional: true },
password: { label: "Password", type: "password"},
mobile:{ label:"Mobile", type:"text", optional: true},
school:{ label:"School", type:"text", optional: true}
},
async authorize(credentials) {
let validatedCredentials: {
email: string;
username?: string;
password: string;
mobile?:string;
school?:string;
};
try {
validatedCredentials = authSchema.parse(credentials);
} catch (error) {
console.log("Wrong credentials. Try again.");
return null;
}
const { email, password } = validatedCredentials;
const [existedUser] = await db
.select({
id: usersTable.displayId,
username: usersTable.username,
email: usersTable.email,
provider: usersTable.provider,
hashedPassword: usersTable.hashedPassword,
mobile: usersTable.mobile,
authority: usersTable.authority,
school: experiencesTable.school
})
.from(usersTable)
.leftJoin(experiencesTable, eq(usersTable.email, experiencesTable.email))
.orderBy(desc(experiencesTable.semester))
.where(eq(usersTable.email, email.toLowerCase()))
.limit(1)
.execute();
if(!existedUser){
return null;
}
const isValid = await bcrypt.compare(password, existedUser.hashedPassword);
if (!isValid) {
throw new Error("輸入的密碼不正確,請再次輸入");
}
return {
email: existedUser.email,
username: existedUser.username,
id: existedUser.id,
mobile: existedUser.mobile,
authority:existedUser.authority,
school: existedUser.school??""
};
},
});
The signIn and signOut works fine before I add result(the variable returned in signIn function) and throw new Error in CredentialsProvider.ts
(before both !existedUser
and !isValid
return null), so the error might occurs because of router.push()
and router.refresh()
.
Because I want to toast different words when users type their account and password wrong, so I guess I still needs result(the variable returned in signIn function) to see if it is a CredentialsSignin error or CallbackRouteError.
I want to know whether my guess of why the error is showing is right and how to fix it without removing the part where I determine what kind of error is the signIn function returning. Thanks!
Providing my auth/signout
if needed:
"use client";
import { useEffect } from "react";
import { signOut, useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { publicEnv } from "@/lib/env/public";
function SignOutPage() {
const { data: session } = useSession();
const router = useRouter();
useEffect(() => {
if (session) {
signOut({ callbackUrl: publicEnv.NEXT_PUBLIC_BASE_URL });
}
router.push("/");
}, [session, router]);
return <></>;
}
export default SignOutPage;
Also how I signOut:
<a href="/auth/signout" className="hover:opacity-70">登出</a>
Upvotes: 0
Views: 121