Relative Cursor Based Pagination with GraphQL and React

Solved
Highlighted
Pathfinder
83 4 11

I want to implement cursor based pagination have not managed to get the "hasNext" click to return the next page of results. The area I am having trouble with is the fetchMore and updateQuery section. I've followed: 

My GraphQL query works when manually passing the intended variables:

 

const GET_NEXT_PRODUCTS = gql`
query ($cursor: String){
  products(first: 10, after: $cursor) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        id
        title
        handle
        description
        images(first: 1) {
          edges {
            node {
              originalSrc
              altText
            }
          }
        }
        variants(first: 1) {
          edges {
            node {
              taxCode
              price
              id
              taxable
            }
          }
        }
      }
    }
  }
}
`

 

 

My Query component is here: 

 

    <Query query={GET_NEXT_PRODUCTS}
      notifyOnNetworkStatusChange
    >
      {({ data, loading, error, fetchMore }) => {
        if (loading) return <div>
          <Frame>
            <Spinner accessibilityLabel="Spinner" size="large" color="teal" />
          </Frame>
        </div>;
        if (error) return <div>
          <Banner
            title={error.message}
            status="critical"
          >
            <p>{error.stack}</p>
          </Banner>
        </div>;
        console.log(data);
        return (
          <Page
            fullWidth
            title="Products"
          >
            <Card>
              <ResourceList
                showHeader
                items={data.products.edges}
                promotedBulkActions={promotedBulkActions}
                bulkActions={bulkActions}
                resourceName={resourceName}
                renderItem={renderItem}
                selectedItems={selectedItems}
                onSelectionChange={setSelectedItems}
              />
            </Card>

            {data.products &&
              data.products.pageInfo.hasNextPage && (
                <Pagination
                  hasPrevious
                  onPrevious={() => {
                    console.log('Previous');
                  }}
                  hasNext
                  onNext={() => {
                    console.log('Clicked Next');
                    console.log(data.products.edges);
                    console.log('0: ' + data.products.edges[0].cursor);
                    console.log('9: ' + data.products.edges[numProducts - 1].cursor);
                    fetchMore({
                      query: GET_NEXT_PRODUCTS,
                      variables: {
                        cursor: cursor
                      },
                      updateQuery: (previousResult, { fetchMoreResult }) => {
                        const previousEntry = previousResult.products;
                        const newProducts = fetchMoreResult.products;
                        const newCursor = fetchMoreResult.products.edges[numProducts - 1].cursor;
                        return {
                          cursor: newCursor,
                          entry: {
                            products: newProducts
                          }
                        };
                      }
                    })
                  }}
                >
                </Pagination>
              )
            }
          </Page>
        );
      }}
    </Query>

 

 

Right now I have just tried implementing the hasNext but also need to understand how to get the hasPrevious and return the earlier page. 

I have not found easy to understand documentation on this specific step and would really appreciate any guidance on how to implement this. 

0 Likes
Highlighted
Shopify Expert
4265 32 434

This is an accepted solution.

I render the cursor value from before and after into the controls for prev and next buttons.

When I get data, if there is a next or previous page I am simply echoing that out as booleans into my components. So if next is true, a click on the next sends the after cursor to the query. I get back the next page. Same for previous. If no previous page exists, the button, she no work. Simple.

The one thing I learned from all this, that I did not know, was it is OK to provide a before or after cursor with a nil String value! With that, I can limit my GQL to only two queries. Before and After. I used to think (naively) that I needed an initializer, to setup the case where before or after are nil. Silly me.

I never use JS and Apollo so I cannot help with that. I just use Axios to send a request for data to my App, and my App returns data. I think Apollo is for fancy smancy Apps way beyond anything I would use with Shopify. It seems nice though. I guess once you get used to it as a thing, it makes sense to use it. I just hate adding an extra 100,000 lines of someone else's JS to a project, and trying to keep up with those Joneses. It is hard enough just keeping up with the basic CRUD.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Highlighted
Shopify Expert
4265 32 434

Oops. I get it now. Apollo would be used by people using JS to do their GraphQL calls. Since I would never use JS for my server, that is probably why I never use Apollo!

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com