React NextAuth中Credentials为null且认证功能失效求助
问题描述
- 出现报错:
Cannot convert undefined or null to object - 添加
{ providers !== null && ... }屏蔽错误后,页面可加载但认证完全失效,触发无反应 - 表单提交事件能触发,但
signIn("credentials"...)未执行
第三方登录按钮渲染代码
return ( <> {Object.values(providers).map((provider) => { if (provider.id === "credentials") { return null; } return ( <div key={provider.name}> <Button variant="outlined" onClick={() => { setAppLoading(true); signIn(provider.id); setAppLoading(false); }} className="w-full uppercase !transform-none mt-4" > <Image height={24} width={24} src={`/logos/${provider.name}.svg` || "/logos/google.svg"} alt={provider.name} /> <span className="ml-2 !text-[rgba(26, 26, 44, 0.5)]"> Sign in with {provider.name} </span> </Button> </div> ); })} </> ); };
表单提交事件代码
import { ClientSafeProvider, signIn } from "next-auth/client"; ... onSubmit={async (values, { setErrors }) => { const { email, password } = values; setAppLoading(true); signIn("credentials", { email, password, redirect: false, }).then((res) => { setErrors({ error: res?.error }); }); setAppLoading(false); }} ...
[...nextauth].ts 配置代码
import login from "features/auth/login"; import register from "features/auth/register"; import NextAuth from "next-auth"; import Providers from "next-auth/providers"; export default NextAuth({ providers: [ Providers.Credentials({ name: "Credentials", credentials: { name: { label: "Name", type: "text" }, email: { label: "Email", type: "text" }, password: { label: "Password", type: "password" }, }, async authorize(credentials, _req) { const { name, email, password } = credentials; alert("clicked"); console.log("CLICKEEEED!!!!!!!!!!!!!!"); if (typeof name === "undefined") { return login(email, password); } return register(name, email, password); }, }), Providers.Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ], pages: { signIn: "/auth/signin", signOut: "/auth/signout", error: "/auth/error", // Error code passed in query string as ?error= verifyRequest: "/auth/verify-request", // (used for check email message) }, session: { jwt: true, maxAge: 30 * 24 * 60 * 60, // 30 days }, });
解决方案
1. 修复Cannot convert undefined or null to object报错
直接判断providers是否存在,同时处理加载状态,避免初始值为null/undefined时调用Object.values:
return ( <> {providers ? Object.values(providers).map((provider) => { if (provider.id === "credentials") { return null; } return ( <div key={provider.name}> <Button variant="outlined" onClick={() => { setAppLoading(true); // 等待登录请求完成再关闭加载状态 signIn(provider.id).finally(() => setAppLoading(false)); }} className="w-full uppercase !transform-none mt-4" > <Image height={24} width={24} src={`/logos/${provider.name}.svg` || "/logos/google.svg"} alt={provider.name} /> <span className="ml-2 !text-[rgba(26, 26, 44, 0.5)]"> 用{provider.name}登录 </span> </Button> </div> ); }) : <div>加载中...</div>} </> ); };
2. 修复signIn("credentials")不执行问题
表单提交里的setAppLoading(false)会在异步请求完成前执行,改用await处理异步逻辑:
onSubmit={async (values, { setErrors }) => { const { email, password } = values; setAppLoading(true); try { const res = await signIn("credentials", { email, password, redirect: false, }); if (res?.error) { setErrors({ error: res.error }); } } catch (err) { setErrors({ error: "登录失败,请重试" }); } finally { setAppLoading(false); } }}
3. 检查Credentials授权逻辑
authorize函数运行在服务端,里面的alert和console.log不会在浏览器控制台输出,调试请用服务端日志- 确保
login和register函数验证成功时返回包含id、name、email的用户对象,验证失败返回null,示例:
async function login(email: string, password: string) { const res = await fetch("/api/auth/login", { method: "POST", body: JSON.stringify({ email, password }), headers: { "Content-Type": "application/json" }, }); const user = await res.json(); return res.ok ? user : null; }
内容的提问来源于stack exchange,提问作者Denzel
相关产品推荐
相关产品推荐

