You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

关键说明

  1. 禁用自动跳转:通过redirect: false让signIn返回Promise结果而非直接跳转,避免组件卸载导致错误信息丢失。
  2. 抛出错误而非返回null:NextAuth中authorize返回null会触发错误页跳转,抛出错误则会让signIn进入catch块,便于捕获服务端错误信息。
  3. 状态存储错误:用useState保存错误信息,确保组件重渲染时错误不会丢失。

内容的提问来源于stack exchange,提问作者Anuj Todankar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:55:05