question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Configuring keyArgs for types rather than fields?

See original GitHub issue

Hey,

I’ve seen that we can specify merge function for types rather than fields. But since typePolicies.Type.keyArgs does not exist - which seems normal since we are talking about a type, not a query field - am I forced to use Query.fields for pagination?

To be more precise: I have an album containing multiple tracks with this schema:

type Album {
  id: ID!
  tracks(first: Int = 20, after: String): AlbumTracksConnection!
}

type AlbumTracksConnection {
  edges: [AlbumTracksEdge!]!
  pageInfo: PageInfo!
}

type AlbumTracksEdge {
  cursor: String!
  node: Track
}

When I want to paginate, I could use the following query:

query Album($albumId: String!, $nb: Int, $after: String) {
  album(albumId: $albumId) {
    id
    tracks(first: $nb, after: $after) {
      pageInfo {
        hasNextPage
        endCursor
      }
      edges {
        cursor
        node {
          id
          title
        }
      }
    }
  }
}

with this fetchMore:

fetchMore({
  variables: {
    albumId: "13",
    nb: 3,
    after: data.album.tracks.pageInfo.endCursor,
  },
})

and this typePolicies:

typePolicies: {
  Album: {
    fields: {
      tracks: relayStylePagination(),
    },
  },
}

Everything works perfectly.

But then, if I want to configure the typePolicies for type over fields, since AlbumTracksConnection is always paginated, I’d try:

typePolicies: {
  AlbumTracksConnection: relayStylePagination(),
}

which does not work as the Album.fields.tracks policy keeps its original keyArgs value.

I would then need to specify Album.fields.tracks.keyArgs to false in the typePolicies for the pagination to work. But then I would loose the benefit of being able to target types over fields name.

So the question is: Do we want to be able to handle pagination/keyArgs via type, like we are able to handle merge? It would ease the pagination for types. Or am I doing something wrong with the pagination?

Probably related: https://github.com/apollographql/apollo-client/pull/7070#issuecomment-736799353

PS: In real life, I’d use a Paginable type like so:

new InMemoryCache({
  typePolicies: {
    Paginable: relayStylePagination(),
  },
  possibleTypes: {
    Paginable: ["AlbumTracksConnection", "AnythingConnection", ...],
  },
});

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
sebastienbarrecommented, Oct 14, 2021

Having worked on pagination in the past few days, I’m not sure how your scenario would work. relayStylePagination() needs access to args.after and args.before to work. These are not defined at the AlbumTracksConnection level, they are defined at the field level, in this case, tracks(first: $nb, after: $after), that’s why relayStylePagination() is associated to the tracks field. Case in point, you could have two different fields returning an AlbumTracksConnection, but with different arguments for each fields.

0reactions
Azerothiancommented, May 12, 2022
type WhereQuery {
  active: Boolean!
}
type Item {
  id: ID!
  children(first: Int = 20, after: String, where: WhereQuery): ItemConnection!
}

type ItemConnection {
  edges: [ItemEdge!]!
  pageInfo: PageInfo!
}

type ItemEdge {
  cursor: String!
  node: Item
}

Type Policy

const itemConnectionTypePolices = {
  ...relayStylePagination(() => ["where"]), // without normalisation
  fields: {
    edges: {
      fields: {
        node: {
          fields: {
            children: itemConnectionTypePolices,
          },
        },
      },
    },
  },
};


const memoryCacheOptions = {
  typePolicies: {
    Item: {
      fields: {
        children: itemConnectionTypePolices,
      },
    },
  },
};

https://www.apollographql.com/docs/react/caching/cache-configuration/#disabling-normalization

  1. Without normalisation you cant run two queries on the same object and one will override the other. But it is the only way data is store in the parent object.
  • This following will override each other without normalisation
    • Item.children.edges[0].node.children(where: {active: false}).edges
    • Item.children.edges[0].node.children(where: {active: true}).edges
  1. With normalisation (ie. supplying keyArgs) the following active: false queries will interfere with each other
  • Item.children(where: {active: false}).edges
  • Item.children(where: {active: true}).edges.node.items(where: {active: false}).edges
  1. Writing the code above is way funky and can be easily cleaned up if we could do it by a Type instead of path.

Ideas

  • Allow for a function to define the actual key instead of providing fields and variable names.
    • We will need the parent object and child obj plus return values.
    • if we could get the full path to the queried object would be a bonus win
  • Allow for the capability to define whether the type will be normalised or not.
  • Allow for type based definitions of policies as a function or an object

@sebastienbarre it should be the type of the field that would be the referring type, which at that point you could supply the args for normalisation / manipulation.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Key arguments in Apollo Client - Apollo GraphQL Docs
A keyArgs array can include the types of values shown below. ... and instead configure keyArgs in your Query.feed field policy: JavaScript.
Read more >
React Apollo Client - query results mixing up in cache
A keyArgs: ["type"] field policy configuration means type is the only argument the cache should consider (in addition to the field name and ......
Read more >
Customizing the behavior of cached fields - Client (React)
Often, it's preferable to concatenate the two arrays instead, like so: ... Suppose that a Book type has an author field, which is...
Read more >
What's New In Python 3.8 — Python 3.11.1 documentation
config ( PyConfig type) fields to these internal structures. PyInterpreterState.config becomes the new reference configuration, replacing global configuration ...
Read more >
Dynamic types and fields - GraphQL Ruby
Then, you can configure fields with for_staff: true|false : ... With that configuration, post { comments { . ... it will use def...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found