Next14如何在全局上下文共享服务端获取的用户认证信息?
Next14 无需
'use client'实现用户信息全局共享方案 核心逻辑
Next14 App Router 支持服务器组件层面的上下文传递,完全绕开客户端的useEffect和'use client'指令,下面提供两种可行方案:
方案一:React Context + 根布局注入(全局共享)
- 定义用户上下文
创建上下文文件,无需添加客户端指令:
// app/context/userContext.tsx import { createContext, useContext, ReactNode } from 'react'; type User = { id: string; name: string; // 补充你的用户字段 } | null; const UserContext = createContext<User | undefined>(undefined); export function UserProvider({ children, user }: { children: ReactNode; user: User }) { return <UserContext.Provider value={user}>{children}</UserContext.Provider>; } export function useUser() { const context = useContext(UserContext); if (context === undefined) { throw new Error('useUser 必须在 UserProvider 内部使用'); } return context; }
- 根布局中获取用户并注入上下文
根布局是服务器组件,可直接调用你的getUser方法,将用户数据传入上下文:
// app/layout.tsx import { UserProvider } from './context/userContext'; import { cookies } from 'next/headers'; async function getUser() { const cookieStore = cookies(); // 注意:无需手动设置cookie头,credentials: 'include'会自动携带当前请求的Cookie const response = await fetch(`http://localhost:3005/api/user`, { method: 'GET', credentials: 'include', headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { return null; // 处理未认证场景 } const user = await response.json(); return user; } export default async function RootLayout({ children, }: { children: React.ReactNode; }) { const user = await getUser(); return ( <html lang="zh-CN"> <body> <UserProvider user={user}> {children} </UserProvider> </body> </html> ); }
- 任意组件中使用用户数据
- 服务器组件直接调用
useUser(),无需任何客户端指令:
// app/components/Nav.tsx import { useUser } from '../context/userContext'; export default async function Nav() { const user = useUser(); return ( <nav> {user ? ( <span>欢迎,{user.name}</span> ) : ( <a href="/login">登录</a> )} </nav> ); }
- 若需在客户端交互组件中使用,仅需在组件顶部添加
'use client'即可(仅交互组件需要,纯展示组件保持服务器组件属性)。
方案二:服务器组件Props传递(轻量共享)
如果不需要全局上下文,可通过根布局获取用户后,逐层通过Props传递给目标组件,全程无需客户端代码:
// app/layout.tsx async function getUser() { /* 同方案一的getUser实现 */ } export default async function RootLayout({ children }) { const user = await getUser(); return ( <html lang="zh-CN"> <body> {React.cloneElement(children as React.ReactElement, { user })} </body> </html> ); } // app/page.tsx export default function Home({ user }) { return ( <div> <Nav user={user} /> {/* 页面其他内容 */} </div> ); } // app/components/Nav.tsx export default function Nav({ user }) { return ( <nav> {user ? <span>欢迎,{user.name}</span> : <a href="/login">登录</a>} </nav> ); }
重要修正提示
你当前的getUser方法存在错误:cookie: cookieStore是无效写法,cookies()返回的是Next.js的CookieStore对象,无需手动在请求头中设置,credentials: 'include'会自动携带当前请求的Cookie。
内容的提问来源于stack exchange,提问作者Ole Dybedokken
相关产品推荐
相关产品推荐

