Next.js 13 + next-auth:useSession与SessionProvider使用报错问题
解决Next.js App Router中NextAuth的SessionProvider配置问题
问题现象
在迁移至App Router的新项目中开发登录页面时遇到两个错误:
- 不添加
"use client"时,报错:Error: React Context is unavailable in Server Components - 添加
"use client"后,报错:Error: [next-auth]: useSession must be wrapped in a <SessionProvider />
原项目中_app.js的SessionProvider迁移到根layout.tsx后未生效,现有代码存在App Router适配问题。
核心原因
App Router的根layout.tsx默认是服务器组件,无法直接使用客户端的Context Provider;同时旧Pages Router的getLayout方式在App Router中不再适用,页面不会自动关联自定义布局中的SessionProvider。
修复方案
1. 创建独立的SessionProvider客户端组件
新建components/SessionProviderWrapper.tsx,将SessionProvider封装为客户端组件:
"use client"; import { SessionProvider } from "next-auth/react"; import { ReactNode } from "react"; type Props = { children: ReactNode; }; export default function SessionProviderWrapper({ children }: Props) { return <SessionProvider>{children}</SessionProvider>; }
2. 修改根layout.tsx
在根布局中引入并使用上述客户端组件,确保所有页面都被SessionProvider包裹:
import Image from 'next/image' import { ReactNode } from "react"; import "./globals.css"; import Link from "next/link"; import SessionProviderWrapper from './components/SessionProviderWrapper'; type Props = { children: ReactNode; }; export default function RootLayout({ children }: Props) { return ( <html lang="en"> <head /> <body> <SessionProviderWrapper> <div className="mx-auto"> <div className="flex flex-row flex-wrap"> <aside className="w-full sm:w-1/3 md:w-1/5 xl:w-1/6 border-r-2 border-[#F845C6]"> <div className="sticky top-0 p-4 w-full"> <ul className="flex flex-col overflow-hidden"> <li className="m-5 text-center"> <Link href="/login">LOGO</Link> </li> <li className="m-5 text-center"> <Link href="/">Dashboard</Link> </li> <li className="m-5 text-center"> <Link href="/tasks">Tasks</Link> </li> <li className="m-5 text-center"> <Link href="/reporting">Reporting</Link> </li> </ul> </div> </aside> <div className="w-full sm:w-2/3 md:w-4/5 xl:w-5/6">{children}</div> </div> </div> </SessionProviderWrapper> </body> </html> ); }
3. 简化Login页面代码
移除Pages Router遗留的getLayout相关代码,App Router会自动使用根布局:
"use client"; import React from 'react' import { useSession, signIn, signOut } from 'next-auth/react' export default function Login() { const { data: session } = useSession(); if (session) { return ( <div style={{ fontFamily: 'sans-serif', margin: '10px 20px' }}> <p>欢迎,{session.user.name}</p> <img src={session.user.image} alt="用户头像" style={{ borderRadius: '15px', width: '80px', margin: '10px' }} /> <button onClick={() => signOut()}>退出登录</button> </div> ); } else { return ( <div> <p>请登录</p> <button onClick={() => signIn("google", { callbackUrl: '/account' })}>使用Google登录</button> </div> ); } }
关键修复点说明
- 将SessionProvider单独封装为客户端组件,规避App Router根布局的服务器组件限制
- 根布局通过客户端组件包裹所有内容,确保全局能访问Session Context
- 废弃Pages Router的
getLayout模式,遵循App Router的自动布局关联规则
内容的提问来源于stack exchange,提问作者atomic-ag
相关产品推荐
相关产品推荐

