NextAuth授权后useState未更新,仅页面刷新后显示会话数据
解决NextAuth登录后Context用户状态不实时更新的问题
问题分析
你的代码存在两个核心问题,导致登录后用户状态为null,必须刷新页面才会显示:
- 服务器端初始值无法同步客户端会话更新:
RootLayout中通过getServerSession获取的会话仅在页面首次渲染时生效,登录后客户端的会话更新不会自动同步到UserProvider的userprops。 - 登录逻辑错误更新状态:
loginUser函数中调用signIn后,直接使用初始传入的userprops(登录前为null)更新状态,并没有获取登录后的最新会话数据。
解决方案
通过结合NextAuth客户端钩子useSession监听会话变化,实现用户状态的实时同步:
1. 修改UserProvider.ts代码
'use client' import { useSession, signIn } from "next-auth/react" import React, { useEffect } from "react" import { useRouter } from "next/navigation" type LoginProps = { email: string password: string } type UserProviderProps = { user: IUser | null loginUser: (login: LoginProps) => Promise<void> setUser: React.Dispatch<React.SetStateAction<IUser | null>> } const UserContext = React.createContext<UserProviderProps>({} as UserProviderProps) export const UserProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const router = useRouter() // 使用NextAuth客户端钩子获取实时会话 const { data: session, status } = useSession() const [current_user, setUser] = React.useState<IUser | null>(session?.user || null) // 监听会话变化,自动更新用户状态 useEffect(() => { if (session?.user) { setUser({ ...session.user }) } else { setUser(null) } }, [session]) async function loginUser(login: LoginProps) { const result = await signIn('credentials', { ...login, redirect: false }) // 登录成功后无需手动setUser,useSession会自动监听会话变化更新状态 if (result?.ok) { // 可选:登录成功后跳转页面 // router.push('/dashboard') } } const value = React.useMemo(() => { return { user: current_user, loginUser, setUser, } }, [current_user]) return <UserContext.Provider value={value}>{children}</UserContext.Provider> } export const useUser = () => React.useContext(UserContext)
2. 简化layout.ts代码
由于UserProvider现在会通过useSession自动获取客户端会话,不再需要从服务器端传递user props:
export default async function RootLayout({children}: {children: React.ReactNode}) { // 服务器端会话仍可保留,用于页面初始渲染的权限判断等场景 const session: Session | null = await getServerSession(authOptions) return ( <html> <body> <AuthProvider> <UserProvider> <Providers> {children} </Providers> </UserProvider> </AuthProvider> </body> </html> ) }
关键改动说明
- 引入
useSession钩子:实时监听客户端会话变化,替代仅依赖服务器端初始值的逻辑。 - 添加
useEffect监听会话:当会话更新(如登录、登出)时,自动同步current_user状态。 - 修正登录逻辑:登录成功后不再手动设置旧的
user值,而是依赖useSession的自动更新机制。
内容的提问来源于stack exchange,提问作者Free
相关产品推荐
相关产品推荐

