如何在 apollo 客户端策略中使用 readField 来选择具有参数的查询

Posted

技术标签:

【中文标题】如何在 apollo 客户端策略中使用 readField 来选择具有参数的查询【英文标题】:How to use readField in apollo client polices for sub selecting a query that has arguments 【发布时间】:2021-10-16 01:22:39 【问题描述】:

使用@apollo/client 3.4.7

我一直在关注 Dan Reynolds https://www.apollographql.com/blog/apollo-client/architecture/redux-to-apollo-data-access-patterns/ 的这篇很棒的博客,它解释了从 Redux 世界到 Apollo GraphQL 世界的转变。 Redux 的一个不错的部分是能够使用选择器从您的状态中选择部分数据。在 Apollo 领域,您可以运行查询,但有时您已经拥有数据并且只需要其中的一个子集。该博客详细介绍了您可以执行以下操作:

const schema: TypePoliciesSchema = 
  typeDefs: gql`
    extend type Query 
      readManagers: [Employee!]!
    
  `,
  typePolicies: 
    Query: 
      fields: 
        readManagers: 
          read(employees, context) 
            const employees = readField<Query, 'readEmployees'>(context, 'readEmployees');

            return employees.filter(employeeRef => 
              const employeeRole = readField<Employee, 'role'>(context, 'role', employeeRef);
              return employeeRole === EmployeeRole.Manager;
            );
          ,
        
      
    
  

这是基于一个简单的 GraphQL 查询:

query GetEmployees 
  employees 
    id
    name
    role
    team
  

我的问题是,当您的查询有参数时,如何获得查询结果:

query GetEmployees($companyId: ID!) 
  employees(companyId: $companyId) 
    id
    name
    role
    team
  

您突然无法访问 readEmployees,因为缓存键现在类似于 readEmployees("companyId": "uuid")

我很感激您可能还必须设置 readManagers 查询以使用参数,以获得相同的 ID 才能进行子选择。我尝试手动伪造查询键以匹配,但没有成功。

我目前的工作是使用上下文中的缓存并运行相同的查询,并且许多使用 toReference 将它们转换为引用:

const schema: TypePoliciesSchema = 
  typeDefs: gql`
    extend type Query 
      readManagers: [Employee!]!
    
  `,
  typePolicies: 
    Query: 
      fields: 
        readManagers: 
          read(employees, context) 
            const employees = context.cache.readQuery('readEmployees',  variables:  companyId: context.args.companyId || context.variables.companyId   );
            return employees.filter(employeeRef => 
              const employeeRole = readField<Employee, 'role'>(context, 'role', employeeRef);
              return employeeRole === EmployeeRole.Manager;
            );
          ,
        
      
    
  

这感觉不是最好的解决方案,而且感觉像是读取缓存的子选择的大量样板。

【问题讨论】:

将参数添加到扩展查询 (readManagers) ? 我在工作中,我已经使用上下文中的 args 将变量提供给内部 readQuery。我的问题是关于如何使用 readField,但我的印象是,除非您使用基本的 graphql 查询,否则这是不可能的。 【参考方案1】:

根据github issue 的回答,您可以使用另一种形式的 readField 函数,它接受对象。 然后你可以在你的类型策略定义中使用它来读取带有参数的数据

 users: 
        read(users,  args, readField ) 
             const  where:  id   = args;

             const users = readField(
                fieldName: 'Users',
                args:  where:  id  ,
              );

             return users;
        ,
   

【讨论】:

以上是关于如何在 apollo 客户端策略中使用 readField 来选择具有参数的查询的主要内容,如果未能解决你的问题,请参考以下文章

Express CORs 策略阻止 Apollo 客户端从服务器获取

如何手动将 apollo 自定义标量映射到客户端类型

如何在单个项目中使用多个版本的 Apollo 客户端

如何在生产中使用 apollo 订阅

Apollo 客户端和在线/离线事件

在 Apollo Nuxt 中,如何在方法中访问非默认客户端?