Utilizing version 3.4.7 of @apollo/client
I came across an informative blog post by Dan Reynolds here. The blog delves into transitioning from a Redux environment to an Apollo GraphQL setup. In Redux, selectors are handy for extracting specific data from the state. However, in Apollo, although you can run queries, sometimes you already possess the required data and simply need a subset of it. The article elaborates on achieving this with code like:
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;
});
},
}
}
}
}
}
This sample is based on a straightforward GraphQL query:
query GetEmployees {
employees {
id
name
role
team
}
}
The question arises when dealing with parameterized queries like:
query GetEmployees($companyId: ID!) {
employees(companyId: $companyId) {
id
name
role
team
}
}
Accessing readEmployees becomes tricky in such scenarios due to the altered cache key format like
readEmployees({"companyId": "uuid"})
?
One approach could be modifying the readManagers query to include parameters as well, ensuring the same ID is used for sub-selection. Attempting to manually match query keys might not yield the desired outcome.
A current workaround involves utilizing the context cache to rerun the query and convert the results to references using 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;
});
},
}
}
}
}
}
While effective, this workaround may not be optimal and seems to involve excessive boilerplate for fetching a subset of the cache.