Apollo 链路状态默认解析器不工作(@client 查询参数变量)

Posted

技术标签:

【中文标题】Apollo 链路状态默认解析器不工作(@client 查询参数变量)【英文标题】:Apollo Link State Default Resolver Not Working (@client query parameter variables) 【发布时间】:2018-11-03 01:17:09 【问题描述】:

此处示例:https://codesandbox.io/s/j4mo8qpmrw

这里的文档:https://www.apollographql.com/docs/link/links/state.html#default

TLDR:这是一个待办事项列表,@client 查询参数不会过滤掉该列表。


这是查询,以$id为参数

  const GET_TODOS = gql`
    query todos($id: Int!) 
      todos(id: $id) @client 
        id
        text
      
    
  `;

查询在那里传递变量

<Query query=GET_TODOS variables= id: 1 >

  /* Code */

</Query>

但默认解析器不使用该参数,您可以在上面的codesandbox.io示例中看到它。

文档说它应该可以工作,但我似乎无法弄清楚我错过了什么。提前致谢!

【问题讨论】:

【参考方案1】:

对于简单的用例,您通常可以依靠the default resolver 来获取您需要的数据。但是,要实现过滤缓存中的数据或操作它(就像您对突变所做的那样),您需要编写自己的解析器。为了完成你想做的事情,你可以这样做:

export const resolvers = 
  Query: 
    todos: (obj, args, ctx) => 
      const query = gql`
          query GetTodos 
            todos @client 
              id
              text
            
          
        `
      const  todos  = ctx.cache.readQuery( query )
      return todos.filter(todo => todo.id === args.id)
    ,
  ,
  Mutation: ,

编辑:我们定义的每个类型都有一组字段。当我们返回特定类型(或类型列表)时,该类型上的每个字段都将利用默认解析器来尝试解析自己的值(假设请求了该字段)。默认解析器的工作方式很简单——它查看父(或“根”)对象的值,如果找到与字段名称匹配的属性,则返回该属性的值。如果未找到该属性(或无法强制转换为该字段期望的任何 Scalar 或 Type),则返回 null。

这意味着我们可以,例如,返回一个表示单个 Todo 的对象,并且我们不必为其 idtext 字段定义解析器,只要该对象具有 id 和 @ 987654327@ 属性就可以了。换个角度看,如果我们想在 Todo 上创建一个名为 textWithFoo 的任意字段,我们可以保持缓存默认值不变,并创建一个类似

的解析器
(obj, args, ctx) => obj.text + ' and FOO!'

在这种情况下,默认解析器对我们没有好处,因为存储在缓存中的对象没有 textWithFoo 属性,因此我们编写了自己的解析器。

要记住的重要一点是,像todos 这样的查询也只是一个字段(在这种情况下,它是查询类型上的一个字段)。它的行为与任何其他字段的行为几乎相同(包括默认解析器行为)。但是,使用apollo-link-state,您在defaults 下定义的数据结构将成为您查询的父值或“根”值。

在您的示例代码中,您的 defaults 包含一个属性 (todos)。因为这是根对象上的一个属性,所以我们可以使用名为 todos 的查询来获取它,即使没有解析器也仍然可以取回数据。 todos 字段的默认解析器将查看根对象(在本例中为您的缓存),查看名为 todos 的属性并将其返回。

另一方面,像todo(单数)这样的查询在根(缓存)中没有匹配的属性。您需要为其编写一个解析器以使其返回数据。同样,如果您想在查询中返回数据之前对其进行操作(带或不带参数),则需要包含一个解析器。

【讨论】:

感谢您花时间发布此内容,文档有点混乱。它说如果属性名称匹配(这里就是这种情况),则不需要默认解析器。 evernote.com/l/APeyXGuc1rFApYBdQtLP90j04-q2jddIM3E @Webber 请看我上面的编辑。希望澄清一些事情 您提到 todo 没有匹配的属性,但我们的查询是 todos(即使它只返回 1 个 todo)。所以我的理解是形状需要完全匹配,包括数组的大小? 我提到了todo 作为一个例子,你不能只用默认的解析器来查询。数组的大小无关紧要。 我不确定我可以进一步澄清什么。 todos 的默认解析器按预期返回默认值中的所有待办事项。默认解析器不会对传递给它们的参数做任何事情。如果您想使用参数来过滤或以其他方式操作缓存中的数据,您需要编写自己的解析器,就像我在上面的答案中显示的那样。

以上是关于Apollo 链路状态默认解析器不工作(@client 查询参数变量)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Apollo 链路状态缓存实现客户端过滤

Apollo 链接状态与内置 React 状态

Docker Compose、Nginx、解析器不工作

Apollo 客户端解析器仅触发一次

使用 TypeGraphQL 在浏览器中为 Apollo 本地状态生成 typedef 和解析器

Apollo GraphQL:增强而不是覆盖默认解析器行为