NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?

Posted

技术标签:

【中文标题】NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?【英文标题】:NextJS + Apollo: How to get multiple queries on apolloClient.query inside getServerSideProps? 【发布时间】:2021-10-08 16:31:51 【问题描述】:

我目前正在学习 NextJS + Apollo,但遇到了一个问题。因为不推荐getInitialProps,所以我使用getServerSideProps。在这里,我使用此代码来获取服务器端的 props 并填充组件:

export async function getServerSideProps() 
  // eslint-disable-next-line no-debugger
  const apolloClient = initializeApollo();

  await apolloClient.query(
    query: GET_BANNER_DATA,
  );

  return addApolloState(apolloClient, 
    props: ,
  );

问题在于getServerSideProps 只能用于页面级别,不能用于组件。因此,我必须为我在此页面上使用的所有组件获取道具。

我该怎么做? apolloClient.query接受多个查询吗?或者我应该对addApolloState函数做些什么?

官方文档没有考虑到这一点,我在另一个开源项目中找不到类似的东西。

【问题讨论】:

【参考方案1】:

我认为getServerSideprops 应该只用于页面本身。但是,您可以在页面上包含多个组件,并让每个组件查询自己的数据客户端。

const Page = () => 
  return <Component/>


...

const Component = () => 
  // do query here

【讨论】:

1.这意味着我应该将所有组件放在一个文件中。如果是这样,这是一个坏主意,对吧? 2.即使我这样做,我相信我也只能使用一次getServerSideProps,我最初的问题仍然存在。 3. 我在标题中提到了 Apollo,所以我很想得到一个包含 Apollo 函数的答案。我知道如何使用其他方法(获取等)来做到这一点,但我似乎无法找到答案。不过还是谢谢! 1.不,您可以在任何地方创建组件并导入它们,您不需要在同一个文件中创建它们。 2.您最初的问题不存在,忘记getServerSideProps,这无关紧要,只需将组件用于您的用例即可。 3. 你可以在每个组件中使用 useQuery(Query) 或 client.query,如果你想知道 apollo 是如何工作的,那就提出一个新的问题。忘记尝试获取道具服务器端,获取数据客户端。 1.是的,我可以导入它们,但我不能在导出时进行查询(或者这样做会很复杂)。 2. 不,我需要getServerSideProps,因为我必须在服务器端呈现页面以用于 SEO。我只知道如何在客户端执行此操作。 3.与第2点相同。我知道我可以在组件内部使用useQuery(Query),但我想知道如何在服务器端执行此过程。【参考方案2】:

您可以在一个查询中组合查询。举个例子吧。

query posts($month: Int!) 
  posts(month: $month) 
    id,
    name,
  


query notes($month: Int!) 
  notes(month: $month)
    id,
    name,
  

可以合二为一:

query postsAndNotes($month: Int!) 
  posts(month: $month) 
    id,
    name,
  
  notes(month: $month)
    id,
    name,
  

查询结果会有帖子和笔记对象。

【讨论】:

我认为这不是我的解决方案。我已经为每个组件分离了查询并给出了一个变量;这就是为什么您在我的情况下看到“GET_BANNER_DATA”而不是查询的原因。我可以这样做吗?为什么要使用变量? 我明白你的意思。要在 getServerSideProps 上运行它,您需要获取所有内容并将它们传递给您的组件,除非您不考虑客户端获取。创建一个查询来获取您想要的所有数据。如果您的其他查询取决于某些参数,您需要弄清楚您的调用顺序和架构。【参考方案3】:

在我看来,解决这个问题有两种可能的选择。对于它们两者,您都需要确保可以在页面级组件中导入必要的查询。我喜欢通过在使用它的组件的文件中定义查询,然后将其导出,这样当您描述的页面出于性能原因需要它时,他们可以导入它并保持相对干燥。

从那里,我将假设查询不相互依赖(即,一个查询的结果被输入到下一个查询的变量中)。

解决方案 1 涉及将两个查询组合成一个查询,然后发出该请求。我还没弄明白。

不过,解决方案 2 涉及利用 Promises,特别是 Promise.all

const query1 = apolloClient.query(
    query: GET_BANNER_DATA,
  );

const query2 = apolloClient.query(
    query: SOME_OTHER_QUERY,
  );

Promise.all([query1, query2]).then(
    (responses) => 
      // Do some manipulation of the data responses
    
  );

return addApolloState(apolloClient, 
    // You'll pass whatever props you need for the page to render here,
    // but shouldn't need to do anything for the sub-components.
    // When they go to make their queries, the data will already be in the local Apollo cache
    props: ,
  );

【讨论】:

以上是关于NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 NextJS 服务器为 Apollo 客户端补充水分

如何在 NextJS 应用程序中从 Apollo 链接上下文访问 Express HTTP 请求?

作为道具传递与提取缓存 Apollo 客户端 Nextjs

如果你有 apollo react 钩子从后端获取数据,你如何使用 nextjs 进行服务器端渲染?

NextJS/Typescript/Apollo 错误;类型上不存在属性

在 nextJS 上配置 apollo 客户端以进行订阅的问题