无法在单个 GraphQL 查询中组合本地和远程数据(Next.js + Apollo)

Posted

技术标签:

【中文标题】无法在单个 GraphQL 查询中组合本地和远程数据(Next.js + Apollo)【英文标题】:Unable to combine local and remote data in a single GraphQL query (Next.js + Apollo) 【发布时间】:2019-06-19 16:09:07 【问题描述】:

设置:

我的基本设置是从 GraphQL API 查询数据的 Next.js 应用。

我正在从 API 获取一个对象数组,并且能够在客户端上显示该数组。

我希望能够根据 API 架构中定义的枚举值过滤数据。我能够以编程方式传递这些值,并且数据已正确更新。

我希望这些过滤器在用户离开页面并返回时保持不变。我最初打算使用 Redux,但后来我读到了 apollo-link-state 以及将本地(客户端)状态存储到 Apollo 存储中的能力,所以我开始使用它。到目前为止,一切顺利。

问题:

当我尝试将本地查询和远程查询合并为一个时,出现以下错误:networkError: TypeError: Cannot read property 'some' of undefined

我的查询如下所示:

const GET_COMBINED = gql`
  
    items 
      id
      details
    
    filters @client
  
`

我在这样的组件中使用它:

export default const Items = () => (
  <Query query=GET_COMBINED>
    ( loading, error, data:  items, filters  ) => 
      ...do stuff...
    
  </Query>
)

如果,我单独运行查询,如下所示:

const GET_ITEMS = gql`
  
    items 
      id
      details
    
  
`
const GET_FILTERS = gql`
  
    filters @client
  
`

并将查询嵌套在组件内:

export default const Items = () => (
  <Query query=GET_ITEMS>
    ( loading, error, data:  items  ) => 
      return (
        <Query query=GET_FILTERS>
          ( data:  filters  ) => 
            ...do stuff...
          
        </Query>
      )
    
  </Query>
)

然后它按预期工作!

但是,当单个查询(至少在理论上)可以完成这项工作时,像这样嵌套查询似乎远非最佳。而且我真的不明白为什么组合查询不起作用。

我已经将我的应用程序剥离到它的基本框架以试图理解,但它的要点是,每当我尝试将获取本地和远程数据合并到一个查询中时,它都会惨遭失败,而在孤立的情况下两者都可以正常工作.

问题是否来自 s-s-r/Next?我做错了吗?提前感谢您的帮助!

编辑 2 - 其他详细信息

该错误是由 react-apollo 的 getDataFromTree 触发的,但是即使我在 s-s-r 期间选择跳过查询(通过将 s-s-r: false 属性传递给 Query 组件),组合查询仍然失败。此外,远程和本地查询在单独运行时都在服务器端工作。我很困惑。

我已经根据 NextJS 的 with-apollo 示例整理了一个小型 repo,该示例在此处重现了该问题:https://github.com/jaxxeh/next-with-apollo-local

应用运行后,直接点击Posts (combined)链接会触发错误,而Posts (split)链接会按预期显示数据。

加载数据后,Posts (combined) 将显示数据,但尝试加载额外数据将触发错误。重新加载(即服务器渲染)页面也会触发错误。复选框将起作用,并且它们的状态会在整个应用中保留。

Posts (split) 页面将完全按预期运行。您可以加载额外的帖子数据、重新加载页面和设置复选框。

因此,组合查询显然存在问题,无论是在服务器端(重新加载错误)还是客户端(无法显示其他帖子)。但是,直接写入本地状态(完全绕过查询)确实有效。

为了简洁明了,我删除了 Apollo 初始化代码,它可以在上面链接的 repo 中找到。谢谢。

【问题讨论】:

请包含您的 Apollo 客户端配置,至少包含与 apollo-link-state 相关的位,例如默认值、解析器等。 @DanielRearden 我已经添加了 Apollo 客户端初始化代码。谢谢。 另外,没有解析器,因为不需要解析器。根据4个复选框的状态覆盖整个数组,并且根据数组中包含的值初始设置复选框。 @DanielRearden 使用错误的完整工作示例的 repo 编辑了问题 我无法重现上述错误,但我确实看到Cannot read property 'Query' of undefined 被抛出。添加解析器映射修复了错误,我能够很好地渲染两个组件。 【参考方案1】:

添加一个空对象作为解析器映射到您传递给withClientState 的配置:

const stateLink = withClientState(
  cache,
  defaults: 
    filters: ['A', 'B', 'C', 'D']
  ,
  resolvers: ,
  typedefs: `
    type Query 
      filters: [String!]!
    
  `,
)

有一个相关问题here。如果缺少选项或文档更清楚,构造函数会抛出某种错误,那就太好了。

【讨论】:

哇。非常感谢丹尼尔!我曾尝试通过各种解析器,但从来没有一个空对象! 掌心

以上是关于无法在单个 GraphQL 查询中组合本地和远程数据(Next.js + Apollo)的主要内容,如果未能解决你的问题,请参考以下文章

无法使用远程服务器进行本地身份验证

具有远程存储但在本地查询的组合框

在 Apollo GraphQL 中跨本地和远程模式的嵌套数组中建模数据的最佳方法?

组合查询

单个 GraphQL 查询中的多个源 (Gatsby)

GraphQL 从 MySQL 连接查询返回 null