HoudiniGraphql / houdini

The disappearing GraphQL framework

Home Page:http://www.houdinigraphql.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

@paginate in fragments does not work correctly

samuel-utbult-oborgen opened this issue ยท comments

Describe the bug

It is currently not allowed to have two fields with the @paginate directive in one GraphQL query. However, having a field with the @paginate directive and an included fragment where a field has the @paginate directive is permitted by the compiler. Nevertheless, this causes some odd behaviors.

Calling loadPreviousPage or loadNextPage works as expected for the field declared directly in the query, yet the field declared in the fragment will have its initially loaded elements repeated. The pagination seems to be ultimately controlled from the field declared directly in the query since no more elements will be loaded when the beginning or end is reached for that field regardless of the status of the fragment field.

Additionally removing @paginate from the field declared directly in the query results in loadPreviousPage and loadNextPage not being set, as if the fragment did not exist.

I have a use case where I would like to have multiple fields with @paginate declared in fragments used in other queries. This would make it possible to specify a fragment that a component would require but then a +page.gql query could fulfill, which would be used for paginated dropdown lists in a form in my case.

I propose one way to implement this could be to have one field on the store for each paginated field where loadPreviousPage and loadNextPage could be located, which would control the pagination separately for that field. The linked project with the reproduced bug has examples of this.

I have disabled defaultFragmentMasking if that makes any difference.

Severity

serious, but I can work around it

Steps to Reproduce the Bug

I have reproduced the bug here: https://github.com/samuel-utbult-oborgen/multiple-pagination-example Just start the development environment as usual with npm run dev, go to http://localhost:5173, click on the Prev and Next buttons and read the source code for more explanations.

Reproduction

https://github.com/samuel-utbult-oborgen/multiple-pagination-example

commented

Thank you for reporting and adding the repro ๐Ÿ™

Yes, multiple paginate is also in our mind for a long time. When time allows, we would love to tackle it ๐Ÿ˜Š

Looks like a few of you wants it with all these reactions ๐Ÿ˜‰

I am most likely going to circumvent this problem by using separate client evaluated queries (due to some other factors as well) so I won't put more time into this problem for now. But the bug is still present if you want to take a look at it.

commented

I like the idea of opting to n @paginate with labels. (in your case it's a must, but I'm wondering if we could take this approche in case of many @paginate in general?)

What mode are you targeting Infinite and/or SinglePage?

separate client evaluated queries (due to some other factors as well)

I'm curious, will you share your findings? On discord maybe?


Note that you could do all this manually with something like:

query Info ($afterFirst: ID, $afterSecond: ID) {
    first: pokemon(first: 10, after: $afterFirst) {
        ...SpeciesEdges
    }
    
    second: pokemon(first: 10, after: $afterSecond) {
        ...SpeciesEdges
    }
    ...PokemonFragment
}

And then

// go next first
Info.fetch({ afterFirst: "xxx", afterSecond: Info.variables.afterSecond })

It would be fine with me to write the field name whenever .loadNextPage() or .loadPreviousPage() is called if it means multiple @paginate directives would be supported. I am pretty much always targeting Infinite as I only do cursor pagination and never offset pagination.

I am going to set up a somewhat more complicated example showcasing the kind of page and queries I aim to make (so I will have to respond later). The gist of it is that one page contains a paginated list of customers. These customers can be edited and new ones can be created. Each customer will have a name, a currency and a country. The currency and country can be selected through a dropdown with infinite scrolling. The somewhat easy case is the create case, where the lists starts at the top. The more complicated case is when editing a customer as a currency and a country has to be pre-selected, which means infinite scrolling in both directions needs to be supported.

I have solved this in a previous version of Houdini (where pagination in both directions were not possible) by simply making separate requests and joining the lists together, yet now I would like to do it the proper way. I aim to use only client evaluated queries in the currency and country fields for now but I hope the example could pave a way to somehow have server-side evaluated queries for the fields in the future.

commented

I had a look a bit more in your example ๐Ÿ‘

Random thoughts

  • have the feeling that it should all work if you do @paginate only in fragments.
  • I saw also that you don't have a node interface, maybe you could add it back?
  • Doing defaultFragmentMasking: "disable" should not have any effects in this, but I would not recommend when you start a new project. to try to have all data requirement in 1 component.
  • Any special reason to choose jsDoc over typescript?

I had a look a bit more in your example ๐Ÿ‘

Random thoughts

  • have the feeling that it should all work if you do @paginate only in fragments.
  • I saw also that you don't have a node interface, maybe you could add it back?
  • Doing defaultFragmentMasking: "disable" should not have any effects in this, but I would not recommend when you start a new project. to try to have all data requirement in 1 component.
  • Any special reason to choose jsDoc over typescript?
  • I tried that before without using defaultFragmentMasking: "disable", but Houdini complained about Query not having an id since you require that for any paginated fragments, yet Query does not have any id since there is only one of it.
  • This is based on the hello-houdini project, which does not have a node interface.
  • Okay.
  • That's because hello-houdini uses jsDoc. I always use Typescript otherwise, including in this more complicated example.
commented

Of course it's the intro! ๐Ÿคฆโ€โ™‚๏ธ (too many things turning around)
Do you mind creating a repro with this repo in houdini/e2e/kit? Like this we have everything in place for tests & co :)

Here is a more extensive example of what I am trying to accomplish: https://github.com/samuel-utbult-oborgen/houdini-pagination-example Itโ€™s not perfect but I hope you understand what kind of website Iโ€™m trying to create. Iโ€™ll have to see when I can create a reproduction in houdini/e2e/kit.