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

时间:2019-01-25 19:37:17

标签: graphql apollo react-apollo apollo-client next.js

设置:

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

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

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

我希望这些过滤器在用户离开页面并返回时保持不变。我本来打算使用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>
)

然后按预期运行!

但是,当单个查询(至少在理论上)可以胜任工作时,嵌套这样的查询似乎远非最佳。而且我真的不明白为什么组合查询无法正常工作。

我已将应用程序简化为试图理解,但其要点是,每当我尝试将获取本地和远程数据组合到单个查询中时,它都会惨败,而孤立地运行都很好

问题是来自SSR / Next吗?我做错了吗?预先感谢您的帮助!

编辑2-其他详细信息

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

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

应用运行后,立即单击Posts (combined)链接将触发错误,而Posts (split)链接将按预期显示数据。

一旦加载了数据,Posts (combined)将显示数据,但是尝试加载额外的数据将触发错误。重新加载(即服务器渲染)页面也会触发错误。复选框将可以正常使用,并且其状态在整个应用程序中都将保留。

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

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

为了简洁起见,我删除了Apollo初始化代码,该代码可在上面链接的回购中找到。谢谢。

1 个答案:

答案 0 :(得分:1)

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

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

存在一个相关问题here。如果构造函数如果缺少该选项或文档更加清晰,则抛出某种错误,那将是很好的选择。