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

Paginating over subfield #7135

Closed
PedroBern opened this issue Oct 8, 2020 · 8 comments
Closed

Paginating over subfield #7135

PedroBern opened this issue Oct 8, 2020 · 8 comments
Assignees

Comments

@PedroBern
Copy link

Summary

Hi, I'm coming from Relay where it's super easy to paginate over subfields. However, I'm not managing to achieve this with apollo, can somebody please give me a heads up?

Problem

When the component loads, the query works fine, then when fetchMore is called, all data from the paginating field vanish. In the example below, bar would have results on initial load, then after fetchMore it becomes []. What I'm doing wrong?

Code

query

export const MY_QUERY = gql`
  query foo($pk: uuid!, $offset: Int = 0) {
    foo_by_pk(pk: $pk) {
      bar(limit: 20, offset: $offset) @connection(key: "foo_bar") {
        ...bar_data
      }
    }
  }
  ${Bar_Fragment.data}
`

field policy

const client = new ApolloClient({
  uri: URL,
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          bar: offsetLimitPagination(),
        },
      },
    },
  }),
})

fetch more

const onEndReached = () => {
  fetchMore({
    variables: {
      offset: data.foo.bar.length,
    },
  })
}
@KeithGillette
Copy link
Contributor

I haven't used TypePolicies yet, but is it:

...
    typePolicies: {
      foo_by_pk: {
        fields: {
          bar: offsetLimitPagination(),
        },
      },
    },

@PedroBern
Copy link
Author

PedroBern commented Oct 8, 2020

@KeithGillette thanks for the response, but didn't work :( neither under typePolicies or Query.

Same issue:

...then when fetchMore is called, all data from the paginating field vanish...

@benjamn
Copy link
Member

benjamn commented Oct 9, 2020

@PedroBern What's the type of the object returned for the Query.foo_by_pk field? That's the type whose bar field you should be configuring, rather than configuring Query.bar.

In other words, assuming the type is Foo:

new ApolloClient({
  uri: URL,
  cache: new InMemoryCache({
    typePolicies: {
      Foo: { // instead of Query
        fields: {
          bar: offsetLimitPagination(),
        },
      },
    },
  }),
})

You also do not need the @connection directive, since the offsetLimitPagination helper provides a keyArgs configuration, which is equivalent/superior to @connection (because you configure it once, instead of putting it in every query).

@PedroBern
Copy link
Author

@benjamn thanks it did help! But a new issue came up with your solution:

I have 2 screens:

Screen 1

Simple feed pagination that was working before the solution:

  query FooFeed($offset: Int = 0) {
    foo(limit: 20, offset: $offset,){
      ...FooItem_data
      bar(limit: 1) {
        ...BarItem_data
      }
    }
  }

Screen 2

Details screens that paginate over bar for a given foo. Now this one is working as expected thanks to you. Before your solution, I was needing to query bar with a where constraint.

  query FooDetail($pk: uuid!, $offset: Int = 0) {
    foo_by_pk(pk: $pk) {
      bar(limit: 20, offset: $offset) {
        ...BarItem_data
      }
    }
  }

Type Policies

export const cache: InMemoryCache = new InMemoryCache({
  typePolicies: {
    foo: {
      fields: {
        bar: offsetLimitPagination(), // used in Screen 2 -> Details
      },
    },
    Query: {
      fields: {
        foo: offsetLimitPagination(), // used in Screen 1 -> Feed
      },
    },
  },
})

Question

@benjamn before your solution, the Screen 1 was working and Screen 2 broken. Now it's the opposite. The bar field of Screen 1 is always empty. What am I doing wrong here? Thanks for the help

@benjamn
Copy link
Member

benjamn commented Oct 9, 2020

@PedroBern Can you see what happens if you do bar(offset: 0, limit: 1) instead of bar(limit: 1)?

@PedroBern
Copy link
Author

PedroBern commented Oct 9, 2020

@benjamn Yes actually I have already done it and worked, was coming here to tell you! It's weird that now I need to add some useless arguments in the queries, but it's ok for now. Also, I need to add all key arguments in all queries of the same field, so basically, all my queries that include the bar field need to have offset, limit, and all key arguments (not present in the example), in my case: where and order_by. This is kind of weird.

Thanks for the time you took to help me :)

You can close it now, or maybe let it open, I think it has something to do with #6502

query FooFeed($offset: Int = 0) {
    foo(limit: 20, offset: $offset,){
      ...FooItem_data
      bar(limit: 1, offset: 0) { # add offset to be type policy compliant (?)
        ...BarItem_data
      }
    }
  }

@benjamn
Copy link
Member

benjamn commented Oct 9, 2020

Great to hear! Since that was the problem, I believe offsetLimitPagination can be improved so that it defaults args.offset to zero. I'll fix that shortly.

@hsavit1
Copy link

hsavit1 commented Dec 2, 2020

does this technique also work with relayStylePagination?

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

No branches or pull requests

4 participants