Next.js App Router登录组件无法展示服务端错误的技术求助
解决NextAuth登录表单服务端错误信息丢失问题
要实现登录失败在当前页面展示服务端错误,需要调整NextAuth的授权逻辑和表单提交处理,核心是阻止自动跳转并正确捕获、存储错误信息。
步骤1:修改NextAuth的授权逻辑
在CredentialProvider的authorize函数中,当服务端返回错误时抛出错误而非返回null,这样signIn方法才能捕获到错误信息:
import { NextAuthOptions } from "next-auth"; import GithubProvider from "next-auth/providers/github"; import CredentialProvider from "next-auth/providers/credentials"; export const authOptions: NextAuthOptions = { providers: [ GithubProvider({ clientId: process.env.GITHUB_ID ?? "", clientSecret: process.env.GITHUB_SECRET ?? "", }), CredentialProvider({ name: "credentials", credentials: { email: { label: "email", type: "email" }, password: { label: "password", type: "password" }, }, async authorize(credentials, req) { if (!credentials) return null; const res = await fetch("http://localhost:5000/api/v1/user/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(credentials), }); const user = await res.json(); // 检测服务端错误:根据实际返回结构调整判断条件 if (!res.ok || user.error) { // 抛出包含服务端错误信息的异常 throw new Error(user.message || "操作出错"); } // 登录成功返回用户数据 return user.data ?? null; }, }), ], pages: { signIn: "/", signOut: "/", error: "/not-found", verifyRequest: "/", }, };
步骤2:调整表单提交逻辑
在表单组件中,添加状态存储错误信息,调用signIn时禁用自动跳转,手动处理登录成功/失败的逻辑:
import { useState } from "react"; import { signIn } from "next-auth/react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { UserFormValue, formSchema } from "./your-schema-path"; // 替换为你的Schema路径 // ... const defaultValues = { email: "", password: "", }; const callbackUrl = searchParams.get("callbackUrl"); const form = useForm<UserFormValue>({ resolver: zodResolver(formSchema), defaultValues, }); // 新增状态存储错误信息 const [errorMessage, setErrorMessage] = useState<string | null>(null); const [loading, setLoading] = useState(false); const onSubmit = async (data: UserFormValue) => { setLoading(true); setErrorMessage(null); // 清空之前的错误 try { const response = await signIn("credentials", { email: data.email, password: data.password, callbackUrl: callbackUrl ?? "/dashboard", redirect: false, // 关键:禁止NextAuth自动跳转 }); // 处理登录成功:手动跳转目标页面 if (!response?.error) { window.location.href = callbackUrl ?? "/dashboard"; return; } // 处理NextAuth返回的错误(如授权逻辑未抛出错误但返回null的情况) setErrorMessage(response.error); } catch (error) { // 捕获授权逻辑中抛出的服务端错误 if (error instanceof Error) { setErrorMessage(error.message); } else { setErrorMessage("操作出错"); } } finally { setLoading(false); } };
步骤3:在页面中渲染错误信息
在表单下方添加错误展示的p标签:
<form onSubmit={form.handleSubmit(onSubmit)}> {/* 表单输入项 */} <input {...form.register("email")} /> <input {...form.register("password")} /> <button type="submit" disabled={loading}>登录</button> {/* 展示服务端错误 */} {errorMessage && <p style={{ color: "red", marginTop: "8px" }}>{errorMessage}</p>} </form>
关键说明
- 禁用自动跳转:通过
redirect: false让signIn返回Promise结果而非直接跳转,避免组件卸载导致错误信息丢失。 - 抛出错误而非返回null:NextAuth中
authorize返回null会触发错误页跳转,抛出错误则会让signIn进入catch块,便于捕获服务端错误信息。 - 状态存储错误:用
useState保存错误信息,确保组件重渲染时错误不会丢失。
内容的提问来源于stack exchange,提问作者Anuj Todankar
相关产品推荐
相关产品推荐

