Next.js & RTK Query:无需getInitialProps实现全局页面用户校验
实现方案:Next.js + RTK Query + NextAuth 登录状态校验与动态布局
核心思路
避开getInitialProps的性能问题,也不在_app.tsx硬套服务端逻辑,而是通过NextAuth的客户端API获取登录状态,结合RTK Query的状态管理能力,在客户端层面实现动态布局切换;同时可以搭配NextAuth的服务端中间件做路由保护,兼顾体验和安全。
具体步骤
1. 先搭好NextAuth基础环境
先把认证流程跑通,不用先纠结RTK:
- 安装依赖:
npm install next-auth - 在
pages/api/auth/[...nextauth].ts里配置你的认证提供商(比如账号密码、第三方登录),确保能正常返回用户会话信息 - 用NextAuth的
useSession钩子在任意组件里测试,确认能拿到session对象(包含用户ID、昵称等信息)
2. RTK Query与登录状态联动
RTK Query主要用来拉取用户业务数据(比如个人信息、权限),和NextAuth的会话状态绑定:
- 在RTK Query的API切片里,把NextAuth返回的用户唯一标识(比如
session?.user?.id)作为请求参数,示例:import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const userApi = createApi({ reducerPath: 'userApi', baseQuery: fetchBaseQuery({ baseUrl: '/api/' }), endpoints: (builder) => ({ getUserProfile: builder.query({ query: (userId) => `users/${userId}`, }), }), }); export const { useGetUserProfileQuery } = userApi; - 在需要用户数据的组件里,先拿会话状态再触发请求,没登录就跳过:
import { useSession } from 'next-auth/react'; import { useGetUserProfileQuery } from '@/features/api/userApi'; const Profile = () => { const { data: session } = useSession(); const { data: userProfile } = useGetUserProfileQuery(session?.user?.id || '', { skip: !session, }); // 根据userProfile渲染内容 };
3. 在_app.tsx实现动态头部
直接在_app.tsx里用useSession判断登录状态,切换头部组件:
import { SessionProvider } from 'next-auth/react'; import { AppProps } from 'next/app'; import { Provider } from 'react-redux'; import { store } from '@/app/store'; import LoggedInHeader from '@/components/LoggedInHeader'; import GuestHeader from '@/components/GuestHeader'; export default function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { return ( <SessionProvider session={session}> <Provider store={store}> {/* 根据会话状态切换头部 */} {session ? <LoggedInHeader /> : <GuestHeader />} <Component {...pageProps} /> </Provider> </SessionProvider> ); }
注意:SessionProvider必须包在最外层,确保所有子组件都能获取会话状态;RTK的Provider也要放在正确层级。
4. 路由保护(可选但推荐)
如果需要某些页面必须登录才能访问,用NextAuth的middleware.ts(Next.js 12+支持)做服务端拦截,不用在每个页面写getServerSideProps:
// middleware.ts import { withAuth } from 'next-auth/middleware'; export default withAuth({ callbacks: { authorized({ req, token }) { // 简单判断:有token就是已登录 return !!token; }, }, }); // 指定需要保护的路由 export const config = { matcher: ['/dashboard/:path*', '/profile'], };
5. 优化:自动携带认证令牌
在RTK Query的baseQuery里自动注入NextAuth的令牌,不用每个请求手动加:
import { getSession } from 'next-auth/react'; const baseQuery = fetchBaseQuery({ baseUrl: '/api/', prepareHeaders: async (headers) => { const session = await getSession(); if (session?.user?.token) { headers.set('authorization', `Bearer ${session.user.token}`); } return headers; }, });
注意细节
_app.tsx里确实不能用getServerSideProps,完全依赖客户端的useSession就足够处理布局切换,首次加载时可以加个加载态避免闪烁:const { data: session, status } = useSession(); if (status === 'loading') return <LoadingSpinner />;- 如果某些页面需要服务端渲染用户状态(比如SEO需求),可以在具体页面用
getServerSideProps调用NextAuth的getServerSession,把session传给页面组件,但_app.tsx依然用客户端逻辑处理布局
内容的提问来源于stack exchange,提问作者Ruby
相关产品推荐
相关产品推荐

