我正在尝试注销用户,我正在使用next-auth@beta(不确定这是否有助于解决我的问题,但我只是在这里包含此信息。
这是我的 Jmeter 板侧边栏组件src\components\ap-sidebar.tsx
import { Button, Nav } from 'react-bootstrap';
import styles from './ap-sidebar.module.css';
import { useRouter } from "next/navigation";
export function Sidebar({ activeTab, setActiveTab }: { activeTab: string, setActiveTab: React.Dispatch<React.SetStateAction<string>>}) {
const router = useRouter();
const handleSelect = (selectedTab: string | null, event: React.SyntheticEvent<unknown>) => {
if (selectedTab) {
setActiveTab(selectedTab);
}
};
const handleSignOut = async () => {
try {
const response = await fetch('/api/signout', { method: 'POST' });
if (response.status !== 200) {
console.error("sign out error : " + response.status);
return;
}
const a = await response.json(); // error happens on this line.
console.log(a.message);
router.push('/');
} catch (error) {
console.error(error);
}
};
return (
<Nav variant="pills" className={styles.sidebar} activeKey={activeTab} onSelect={handleSelect}>
<Nav.Item className={styles.navItem}>
<Nav.Link eventKey="artworks">
<i className="bi bi-images"></i>
Artworks
</Nav.Link>
</Nav.Item>
<Nav.Item className={styles.navItem}>
<Nav.Link eventKey="users">
<i className="bi bi-people"></i>
Users
</Nav.Link>
</Nav.Item>
<div className={styles.spaceHolder}></div>
<Nav.Item className={styles.navItem}>
<Button variant="outline-danger" onClick={handleSignOut}>
<i className="bi bi-power"></i> Sign Out
</Button>
</Nav.Item>
</Nav>
);
}
export function ArtworkManager() {
return <div style={{width: "100%"}}>Artwork Manager</div>;
}
export function UserManager() {
return <div style={{width: "100%"}}>User Manager</div>;
}
字符串src/app/api/signout/route.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { NextRequest, NextResponse } from "next/server";
import { signOut } from '../../../../auth';
// export async function POST(req: NextApiRequest, res: NextApiResponse) {
export async function POST(req: NextApiRequest, res: NextApiResponse) {
await signOut();
return res.json({ message: 'Signed out' });
// return res.status(200).json({ message: 'Signed out' });
// return res.end(JSON.stringify({ message: 'Signed out', status: 200 }));
// return new Response(JSON.stringify({ message: 'Signed out', status: 200 }), {
// headers: { 'Content-Type': 'application/json' },
// });
}
型
正如你所看到的,我已经搜索了许多帖子,并尝试了许多不同的方法(注解代码),但错误是如此顽固,总是发生在这行代码:const a = await response.json();
个
错误消息:
语法错误:意外的标记“<$”,“<!DOCTYPE“.不是有效的JSON
任何帮助都很感激。
更新1
我现在使用NextResponse在try/catch块中返回json成功消息。但它直接进入catch块。不知道为什么
x1c 0d1x的数据
更新2
我正在使用
“next”:“^14.0.4”,
“next-auth”:“^5.0.0-beta.4”
我最初的想法是做这样的事情:
import { signOut } from '../../auth';
const handleSignOut = async () => {
"use server"
try {
await signOut({ redirectTo: '/' });
} catch (error) {
console.error(error);
}
};
型
这是auth.ts
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';
import Credentials from 'next-auth/providers/credentials';
import { z } from 'zod';
import { sql } from '@vercel/postgres';
import bcrypt from 'bcryptjs';
async function getUser(email: string): Promise<User | undefined> {
.....
}
export const { auth, signIn, signOut } = NextAuth({
...authConfig,
providers: [
Credentials({
async authorize(credentials) {
const parsedCredentials = z
.object({ email: z.string().email(), password: z.string().min(6) })
.safeParse(credentials);
if (parsedCredentials.success) {
const { email, password } = parsedCredentials.data;
const user = await getUser(email);
if (!user) return null;
const passwordsMatch = await bcrypt.compare(password, user.passwordhash);
if (passwordsMatch) return user;
}
console.log('Invalid credentials');
return null;
},
}),
],
});
型
但是当我这样做的时候,我得到了以下错误。
的
更新3
当在actions.ts
内部的服务器端使用signOut()时,正如@AdamBeleko所提到的,它会像设计的那样抛出异常。所以如果我真的想使用try/catch块,那么这就是我如何做到的。actions.ts
个
export async function handleSignOutServer(): Promise<boolean> {
try {
await signOut();
return true;
} catch (error) {
if ((error as Error).message === 'NEXT_REDIRECT') return true;
console.error('An unexpected error happened during sign out:', error);
throw error;
}
}
型
在我的UI组件中:
<Button variant=“outline-danger”onClick={()=>取消SignOut()}>....
const handleSignOut = async () => {
try {
const success = await handleSignOutServer();
if (success === true)
{
router.push('/');
}
} catch (error) {
console.error(error);
}
};
型
但这似乎过于复杂了。所以为了降低开销的复杂性,我这样做了:actions.ts
个
export async function handleSignOutServer() {
await signOut();
}
型
在UI组件中:
<Button variant="outline-danger" onClick={() => handleSignOutServer()}>
型
这样,就没有额外的代码,而且看起来更漂亮。
1条答案
按热度按时间deikduxw1#
这个问题可能只是你的API路由问题。NextJS 13中的响应是从NextResponse模块解析的,而不是像以前的版本那样从API函数参数解析的。更具体地说,你必须导入并使用
NextResponse
模块:字符串
确保
signout
函数不是客户端函数(可能是API请求)并因此可以在服务器端代码中运行也很重要。**更新:**您遇到的错误与auth的signout函数自动重定向有关,参见:Next 13.4 Error: NEXT_REDIRECT in API routes
要解决此问题,请尝试将重定向选项设置为false:
型
或者,根据文档,直接在客户端的“登录SignOut”函数中使用signout函数,并使用您想要重定向到的路径设置redirectTo选项:
型
参见:https://authjs.dev/reference/nextjs#signout
更新2要在客户端组件中使用服务器函数,请创建一个仅包含服务器函数的文件:
型
稍后,在客户端组件中导入该组件:
型
现在可以在代码中使用该函数了。请确保在客户端组件代码中删除了该函数的Signout回调。
参见:https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#client-components