在NextJS中使用Next-Auth时页面无限重渲染问题求助
问题描述
使用NextAuth实现Google登录时,页面出现无限重渲染,控制台能打印出用户session对象,但页面始终显示「Sign In」按钮,无法切换到「Sign Out」状态。
现有代码
1. /app/api/auth/[...nextauth]/route.js
import NextAuth from "next-auth/next"; import GoogleProvider from "next-auth/providers/google"; export const authOptions = { providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ], }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
2. sessionProvider.js
"use client"; import React from "react"; import { SessionProvider } from "next-auth/react"; const Sessionprovider = ({ children }) => { return <SessionProvider>{children}</SessionProvider>; }; export default Sessionprovider;
3. Layout.js
<html lang="en"> <body className={inter.className}> <Sessionprovider>{children}</Sessionprovider> </body> </html>
4. page.js
"use client"; import { getServerSession } from "next-auth"; import { signIn, signOut, useSession } from "next-auth/react"; import { authOptions } from "./api/auth/[...nextauth]/route"; export default async function Home() { const { data: session, status } = useSession(); console.log(session); const _signInWithGoogle = async () => { await signIn("google"); }; return ( <div className="flex justify-center items-center flex-col gap-3 p-5"> <h1 className="font-semibold text-lg">Home Page</h1> {session ? ( <button onClick={() => signOut()} className="p-1 bg-blue-400 text-white font-semibold rounded-md hover:bg-blue-500" > Sign Out </button> ) : ( <button onClick={_signInWithGoogle} className="p-1 bg-blue-400 text-white font-semibold rounded-md hover:bg-blue-500" > Sign In </button> )} </div> ); }
问题原因
- 客户端组件误用异步函数:标记了
"use client"的组件不能是async function,React会将此类组件判定为不稳定,引发无限重渲染。 - 不必要的服务端API引入:客户端组件中不需要
getServerSession(这是服务端专用API),引入后会触发额外渲染逻辑,加重问题。 - 组件命名不一致(潜在隐患):自定义的Session组件命名为
Sessionprovider(小写p),与NextAuth官方组件名SessionProvider混淆,可能导致状态传递异常。
修复方案
1. 修正page.js
移除async关键字和服务端API相关代码,客户端仅保留useSession:
"use client"; import { signIn, signOut, useSession } from "next-auth/react"; export default function Home() { const { data: session, status } = useSession(); console.log(session); const _signInWithGoogle = () => { signIn("google"); }; return ( <div className="flex justify-center items-center flex-col gap-3 p-5"> <h1 className="font-semibold text-lg">Home Page</h1> {session ? ( <button onClick={() => signOut()} className="p-1 bg-blue-400 text-white font-semibold rounded-md hover:bg-blue-500" > Sign Out </button> ) : ( <button onClick={_signInWithGoogle} className="p-1 bg-blue-400 text-white font-semibold rounded-md hover:bg-blue-500" > Sign In </button> )} </div> ); }
2. 统一Session组件命名(可选但推荐)
修改sessionProvider.js的组件名,与官方保持一致:
"use client"; import React from "react"; import { SessionProvider } from "next-auth/react"; const SessionProvider = ({ children }) => { return <SessionProvider>{children}</SessionProvider>; }; export default SessionProvider;
同步更新Layout.js中的引用:
<html lang="en"> <body className={inter.className}> <SessionProvider>{children}</SessionProvider> </body> </html>
验证修复
重启应用后,页面将停止无限重渲染,且能根据session状态正确切换「Sign In」/「Sign Out」按钮。
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

