You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中用Apollo Client结合getServerSideProps实现组件无传参取数

问题描述

我正在尝试在Next.js中使用apollo-client,希望在getServerSideProps中完成数据获取。当前我有Section、Mobile两个组件以及Home页面:

  • section.tsx(组件1)代码如下:
const Section = () => {
    return (
        <div>
            Section
        </div>
    );
};
export default Section;
  • mobile.tsx(组件2)代码如下:
const Mobile = () => {
    return (
        <div>
            Mobile
        </div>
    );
};
export default Mobile;

我已将这两个组件引入Home页面(index.tsx):

const Home: NextPage = () => {
  return (
    <Container disableGutters maxWidth="xxl">
      <Section />
      <Mobile />
    </Container>
  );
};
export default Home;

export const getServerSideProps: GetServerSideProps = async () => {
  const { data } = await client.query({ query: GET_USER_LIST })
  return { props: {} }
}

我的问题是:如何让Section和Mobile组件无需通过props传递,直接访问这些数据?因为组件树层级加深后,props传递会难以维护。我从Apollo文档了解到apollo-client和redux状态管理器类似,想请教是否可以实现上述需求,若可行该如何操作,若不可行有什么替代方案?

解决方案

完全可以实现你的需求,利用Apollo Client的缓存机制和组件内查询能力即可,无需手动传props,具体步骤如下:

1. 确保Apollo Client全局配置完成

首先要在_app.tsx中用ApolloProvider全局包裹应用,让所有组件都能访问到Apollo Client实例:

import { ApolloProvider } from '@apollo/client';
import client from '../lib/apollo-client';

function MyApp({ Component, pageProps }) {
  return (
    <ApolloProvider client={client}>
      <Component {...pageProps} />
    </ApolloProvider>
  );
}

export default MyApp;

2. 在getServerSideProps中预取数据并写入缓存

你现在的getServerSideProps已经执行了查询,Apollo Client默认会把查询结果自动存入缓存,只要你的client实例是全局共享的,这一步无需额外修改。如果需要确认,可以保持现有代码:

export const getServerSideProps: GetServerSideProps = async () => {
  await client.query({ query: GET_USER_LIST });
  return { props: {} };
};

3. 子组件直接从缓存读取数据

在Section和Mobile组件中使用useQuery钩子查询相同的GET_USER_LIST,Apollo会自动从缓存读取数据,不会发起新的网络请求:

修改后的Section组件:

import { useQuery } from '@apollo/client';
import { GET_USER_LIST } from '../graphql/queries';

const Section = () => {
  const { data, loading, error } = useQuery(GET_USER_LIST);
  
  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error.message}</div>;

  return (
    <div>
      Section - 用户列表:{JSON.stringify(data.userList)}
    </div>
  );
};
export default Section;

修改后的Mobile组件:

import { useQuery } from '@apollo/client';
import { GET_USER_LIST } from '../graphql/queries';

const Mobile = () => {
  const { data, loading, error } = useQuery(GET_USER_LIST);
  
  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error.message}</div>;

  return (
    <div>
      Mobile - 用户列表:{JSON.stringify(data.userList)}
    </div>
  );
};
export default Mobile;

替代方案

如果不想在每个组件中写useQuery,可以用以下两种方式:

  • React Context:在getServerSideProps中获取数据后,存入自定义Context,子组件通过useContext直接读取。
  • 直接读取Apollo缓存:用useApolloClient获取客户端实例,调用readQuery读取缓存数据,注意这种方式需要自己处理数据不存在的情况:
import { useApolloClient } from '@apollo/client';
import { GET_USER_LIST } from '../graphql/queries';

const Section = () => {
  const client = useApolloClient();
  const data = client.readQuery({ query: GET_USER_LIST });

  return (
    <div>
      Section - 用户列表:{data ? JSON.stringify(data.userList) : '无数据'}
    </div>
  );
};

内容的提问来源于stack exchange,提问作者Md Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:11:03