如何将Context API获取的数据传递给getServerSideProps函数?
问题:无法在getServerSideProps中使用Context API获取数据
遇到错误:
React Hook "useContext" is called in function "getServerSideProps" that is neither a React function component nor a custom React Hook function
我的场景是:用Context API在客户端获取数据,想把这些数据传递给getServerSideProps,同时不想在Home组件里直接使用Context,也不想重复写请求代码。
现有代码
AppContext.tsx:
export const AppContext = createContext(null); export const AppContextProvider = ({ children }) => { const [data, setData] = useState([]); useEffect(() => { const fetchData = async () => { const response = await fetch('http://localhost:8080/api/users'); const body = await response.json(); setData(body.users); }; fetchData(); }, []); return ( <AppContext.Provider value={data}>{children}</AppContext.Provider> ); };
index.tsx(路径:apps/ui/pages/index.tsx):
const Home: NextPage<HomeProps> = ({ tiers }) => { const data = useAppContext(); console.log('data', data); // 此处能正常打印数据 return ( <Box> <Head> <title>React App</title> </Head> {data?.map((user) => ( // 渲染用户内容 ))} </Box> ); }; export async function getServerSideProps() { // const data = useContext(AppContext); // 此处触发上述错误 return { props: { data, }, }; } export default Home;
临时方案是在index.tsx里重复写请求逻辑,但不想这么做,希望复用Context里的请求逻辑。
问题原因
getServerSideProps是Next.js的服务器端专属函数,不属于React组件或自定义Hook,完全不遵循React Hook的调用规则,因此不能调用useContext这类Hook。- Context是React客户端渲染周期内的状态容器,服务器端执行
getServerSideProps时,客户端的Context实例还未创建,根本无法访问到Context中的数据。
正确解决方案:抽离复用请求逻辑
把数据请求的核心逻辑抽成独立函数,同时在AppContextProvider和getServerSideProps中复用这个函数,既避免重复代码,又符合Next.js和React的规则。
步骤1:抽离请求函数
创建一个独立的工具文件(比如utils/api.ts),或者直接在AppContext.tsx中导出:
// utils/api.ts export const fetchUsers = async () => { const response = await fetch('http://localhost:8080/api/users'); const body = await response.json(); return body.users; };
步骤2:修改AppContext.tsx,复用请求函数
import { createContext, useState, useEffect } from 'react'; import { fetchUsers } from './utils/api'; export const AppContext = createContext(null); export const AppContextProvider = ({ children }) => { const [data, setData] = useState([]); useEffect(() => { const loadData = async () => { const users = await fetchUsers(); setData(users); }; loadData(); }, []); return ( <AppContext.Provider value={data}>{children}</AppContext.Provider> ); };
步骤3:修改index.tsx,在getServerSideProps中复用请求函数
import { NextPage } from 'next'; import { Box, Head } from '@mui/material'; import { fetchUsers } from '../utils/api'; type HomeProps = { data: User[]; // 定义你的User类型 }; const Home: NextPage<HomeProps> = ({ data }) => { // 直接使用props传递的数据,无需useContext return ( <Box> <Head> <title>React App</title> </Head> {data?.map((user) => ( <div key={user.id}>{user.name}</div> ))} </Box> ); }; export async function getServerSideProps() { const data = await fetchUsers(); return { props: { data, }, }; } export default Home;
方案说明
- 服务器端:
getServerSideProps提前获取数据,通过props传递给Home组件,支持服务端渲染。 - 客户端:如果用户是通过客户端导航进入该页面(比如从其他页面跳转),
getServerSideProps不会执行,此时AppContextProvider中的useEffect会调用复用的请求函数获取数据,保证客户端也能拿到数据。 - 完全避免了重复写请求代码,同时符合Next.js和React的运行规则。
内容的提问来源于stack exchange,提问作者Devmix
相关产品推荐
相关产品推荐

