如何在React Context中复用getServerSideProps用户数据避免重复请求
解决Next.js中用户数据重复请求的方案
核心思路是通过_app.tsx接收所有页面getServerSideProps返回的用户和模板数据,将其注入到UserContext中,让所有子组件直接从Context读取数据,彻底避免重复请求。
1. 改造UserProvider,支持接收服务端初始数据
修改Context代码,让Provider可以接收服务端预取的初始数据,不再在客户端重复发起初始请求:
import React, { useState } from "react"; import Loader from "../components/loader"; import { ContextData } from "../types/customer.type"; import { getAPI } from "../utils/api"; import { parseCookies } from "nookies"; export const UserContext = React.createContext<ContextData>({} as ContextData); // 定义Provider接收的props类型 interface UserProviderProps { children: React.ReactNode; initialUser: ContextData["user"]; initialTemplate?: any; // 替换为你的ITemplate类型 } export const UserProvider = ({ children, initialUser, initialTemplate }: UserProviderProps) => { // 直接用服务端传入的初始数据初始化state const [user, setUser] = useState(initialUser); const [template, setTemplate] = useState(initialTemplate); const [loading, setLoading] = useState(false); // 保留loadUser方法,用于客户端后续主动刷新用户数据(比如token更新后) const loadUser = async () => { setLoading(true); const { 'nextauth.token': token, 'nextauth.refreshtoken': refreshtoken } = parseCookies(); if (token || refreshtoken) { const api = getAPI(); try { const res = await api.get('/v1/auth/me'); setUser(res.data.user); } catch (err) { setUser(null); } } else { setUser(null); } setLoading(false); }; return ( <UserContext.Provider value={{ user, template, loadUser }}> {loading ? <Loader /> : children} </UserContext.Provider> ); };
2. 修改_app.tsx,注入服务端数据到Context
在_app.tsx中,接收页面的pageProps(包含getServerSideProps返回的user和template),并传递给UserProvider:
import type { AppProps } from 'next/app'; import { UserProvider } from '../path-to-your-context/UserContext'; function MyApp({ Component, pageProps }: AppProps) { const { user, template } = pageProps; return ( <UserProvider initialUser={user} initialTemplate={template}> <Component {...pageProps} /> </UserProvider> ); } export default MyApp;
3. 调整页面组件,直接从Context获取数据
所有页面组件无需再处理props传递,直接通过useContext读取数据:
import { useContext } from 'react'; import { UserContext } from '../path-to-your-context/UserContext'; function SomePage() { const { user, template } = useContext(UserContext); return ( <div> {user ? <p>欢迎,{user.name}</p> : <p>请登录</p>} {template && <div>{template.content}</div>} </div> ); } // 保留原有的isAuthStore作为getServerSideProps,无需修改 export const getServerSideProps = isAuthStore(); export default SomePage;
关键说明
- 服务端通过
getServerSideProps统一获取用户和模板数据,仅发起一次请求,通过pageProps传递到_app.tsx后注入Context。 - 客户端初始化时不再重复请求数据,彻底消除重复接口调用的问题。
- 保留的
loadUser方法可用于客户端主动刷新用户数据的场景,不影响初始加载效率。
内容的提问来源于stack exchange,提问作者fnx
相关产品推荐
相关产品推荐

