Как использовать поле чтения в политике клиента apollo для дополнительного выбора запроса с аргументами

#typescript #graphql #apollo

Вопрос:

Использование @apollo/клиент 3.4.7

Я следил за этим замечательным блогом Дэна Рейнольдса https://www.apollographql.com/blog/apollo-client/architecture/redux-to-apollo-data-access-patterns/ что объясняет переход из мира Redux в мир Apollo GraphQL. Приятной частью Redux является возможность использовать селекторы для выбора частей данных из вашего состояния. В Apollo land вы можете выполнять запросы, но иногда у вас уже есть данные, и вам нужно только их подмножество. В блоге подробно рассказывается о том, как вы можете сделать что-то похожее на:

 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 для использования параметров, чтобы получить тот же идентификатор, чтобы иметь возможность сделать дополнительный выбор. Я попытался вручную подделать ключ запроса, чтобы он соответствовал, но это не сработало.

Моя работа на данный момент заключается в том, чтобы использовать кэш из контекста и запускать один и тот же запрос, а многие преобразуют их в ссылки с помощью 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;
            });
          },
        }
      }
    }
  }
}
 

Это не кажется лучшим решением и похоже на большой шаблон для чтения дополнительной выборки кэша.

Комментарии:

1. добавить аргументы в расширенный запрос ( readManagers ) ?

2. В своей работе я использовал аргументы из контекста для предоставления переменных во внутренний запрос чтения. Мой вопрос касается того, как использовать readField, но у меня сложилось впечатление, что это невозможно, если вы не используете базовый запрос graphql.

Ответ №1:

Согласно ответу на вопрос github, вы можете использовать другую форму функции readField, которая принимает объект. Затем вы можете использовать его в определении политики типов для чтения данных с аргументами

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

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

             return users;
        },
   }