Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a relayStylePagination field policy helper function. #6465

Merged
merged 2 commits into from
Jun 22, 2020

Conversation

benjamn
Copy link
Member

@benjamn benjamn commented Jun 19, 2020

This helper function makes it very easy to consume paginated lists from Relay-friendly GraphQL servers, such as the Artsy search API:

import { InMemoryCache } from "@apollo/client"
import { relayStylePagination } from "@apollo/client/utilities"

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        // The ["query"] argument keeps searches separated by args.query (but not
        // by any other arguments, since the field policy will handle them).
        search: relayStylePagination(["query"]),
      },
    },
  },
});

With this field policy in place, you never need to provide an updateQuery function when calling fetchMore for the Query.search field, since the merge function handles that logic far more reliably than any updateQuery function can. Also, you do not need to use any @connection directives in your queries for the field, because that information is expressed by the keyArgs passed to the relayStylePagination function (the ["query"] above).

I made this helper function an export of the @apollo/client/utilities entry point (along with concatPagination and offsetLimitPagination from #6464) so those functions will not be included in your application bundle unless you import and use them. We hope you will find them useable and useful, but we also encourage using them for guidance/inspiration when writing your own custom field policy helper functions.

Note that Apollo Client has no hard-coded logic for Relay connections, edges, nodes, pageInfo, cursors, or forward and backward pagination, because it doesn't need to know anything about these concepts. With enough care, anyone could write the field policy generated by this helper function, which is a considerable testament to the power and flexibility of field policies.

@benjamn
Copy link
Member Author

benjamn commented Jun 19, 2020

@hwillson @jcreighton In observation of Juneteenth, please don't worry about reviewing this today!

@jbaxleyiii I'm not looking for a detailed review from you, but I thought you might like to see how well this ended up working.

Copy link
Member

@hwillson hwillson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, now that's a test! 😂 Looks great @benjamn - thanks!

const index = prefix.findIndex(edge => edge.cursor === args.after);
if (index >= 0) {
prefix = prefix.slice(0, index + 1);
// suffix = []; // already true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be removed?

@benjamn benjamn force-pushed the 5951-fix-fetchMore-merge-variables branch 2 times, most recently from 510b96a to f3676b6 Compare June 22, 2020 15:17
Base automatically changed from 5951-fix-fetchMore-merge-variables to master June 22, 2020 15:50
benjamn added 2 commits June 22, 2020 11:52
This helper function makes it very easy to consume paginated lists from
Relay-friendly GraphQL servers, such as the Artsy search API
(https://metaphysics-production.artsy.net):

  import { InMemoryCache } from "@apollo/client"
  import { relayStylePagination } from "@apollo/client/utilities"

  const cache = new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          // Keep searches separated by args.query (but not by any other
          // arguments, since the field policy will handle them).
          search: relayStylePagination(["query"]),
        },
      },
    },
  });

With this field policy in place, you never need to provide an updateQuery
function when calling fetchMore for the Query.search field, since the
merge function handles that logic far more reliably than any updateQuery
function can. Also, you do not need to use any `@connection` directives in
your queries for the field, because that information is expressed by the
["query"] keyArgs passed to the relayStylePagination function (above).

I made this helper function an export of the the @apollo/client/utilities
entry point (along with concatPagination and offsetLimitPagination) so
those functions will not be included in your application bundle unless you
import and use them. We hope you will find them useful, but we also
encourage using them merely for guidance/inspiration when writing your own
custom field policy helper functions.

Note that Apollo Client has no hard-coded logic for Relay connections,
edges, nodes, pageInfo, cursors, or forwards and backwards pagination,
because it doesn't need to know anything about these concepts. With enough
care, anyone could write the field policy generated by this helper
function, which is a considerable testament to the power and flexibility
of field policies.
@mattlysf
Copy link

mattlysf commented Feb 5, 2021

I can't see any documentation for this ["query"] keyArgs param to relayStylePagination; I have a screen that both does pagination against a relay-style connection API and refreshes the initial set of results periodically via a pollInterval option to the initial query. This option is the only way I've found to get those co-existing nicely, but I can't find any mention of it in the documentation.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants