GraphQL API query pagination not working with cursor

Tolulope_Akinol
Shopify Partner
25 1 1

I have created a recursive function to get all the products in a shop by inserting the cursor of the last node received as the "after" filter of the next query.  However, the function always receives the same first set of products and continues in an infinite loop.  It appears the "after" filter is not being used to run the query.  The query appears to run correctly when run using the GraphiQL app in the shop so it could be that I am doing something wrong.

 

function _getAllShopProducts({defaultProductFields, fields, products=[], cursor=null}) {
  return new Promise((resolve, reject)=>{
    const fetchedFields = fields.length ? fields : defaultProductFields;
    const fragment = `
      fragment productFields on Product {
        ${fetchedFields.join(' ')}
      }
    `;
    const queryPrefix = `
      query getAllShopProducts ($first: Int!,  $cursor: String){
        products(first: $first,  after: $cursor) {
          pageInfo {
            hasNextPage
          }
          edges {
            cursor
            node {
              ...productFields
            }
          }
        }
      }
    `;
    const first = 250;
    const variables = {first, cursor};
    const fullQuery = queryPrefix + fragment;
    this.ShopifyGQL           // prepares the request to the Shopify GraphQL endpoint by setting headers and access code
    .send(JSON.stringify({query:fullQuery, variables}))
    .then((res)=>{
      const edges = res.body.data.products.edges;
      cursor = edges[edges.length-1].cursor;  // set cursor to last node
      let returnedProducts = [];
      edges.forEach((edge)=>{
        returnedProducts.push(edge.node);
      })
      // update products list
      products = products.concat(returnedProducts);
      // if there are no more pages, return the result
      const hasNextPage = res.body.data.products.pageInfo.hasNextPage;
      if(hasNextPage){
        // recurse
        return resolve(_getAllShopProducts.bind(this)({defaultProductFields, fields, products, cursor}))
      } else {
        return resolve(products);
      }
    })
  })
 } 
Replies 5 (5)

Kevin_A
Shopify Staff
318 42 61

Hey @Tolulope_Akinol 

Have you confirmed that $cursor is getting set correctly in your code below? You mentioned it works fine in GraphiQL and based on what I see, the query seems valid. My guess is the cursor isn't being set correctly or potentially is null in your code below which is why it loops infinitely. 

Kevin_A | Solutions Engineer @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

Tolulope_Akinol
Shopify Partner
25 1 1

Thanks for the reply.

 

Yes, I did console.log the cursor variable to see that it was set correctly and it was.

Kevin_A
Shopify Staff
318 42 61

Hey @Tolulope_Akinol 

Thanks for confirming. If the request you are sending from your app is identical to the request you are sending in GraphiQL, then the results will also be identical. If you hardcode the query in your code and ignore the recursive part of your function, does it return the expected results? 

Kevin_A | Solutions Engineer @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

Tolulope_Akinol
Shopify Partner
25 1 1

@Kevin_A It works when hard coded but not when I send the cursor as a variable

 

This works

      const query = `
        query getAllShopProducts  {
          products(first: 1, after: "eyJsYXN0X2lkIjo1NzQ0Nzc1MzMxOTg5LCJsYXN0X3ZhbHVlIjoiNTc0NDc3NTMzMTk4OSJ9") {
            pageInfo {
              hasNextPage
            }
            edges {
              cursor
              node {
                id
                productType
                handle
              }
            }
          }
        }
      `;

      this.ShopifyGQL
      .send(JSON.stringify({query}))

 

But not this

      const cursor = "eyJsYXN0X2lkIjo1NzQ0Nzc1MzMxOTg5LCJsYXN0X3ZhbHVlIjoiNTc0NDc3NTMzMTk4OSJ9"
      const query = `
        query getAllShopProducts ($cursor: String!) {
          products(first: 1, after: $cursor) {
            pageInfo {
              hasNextPage
            }
            edges {
              cursor
              node {
                id
                productType
                handle
              }
            }
          }
        }
      `;

      const variables = {cursor};
      this.ShopifyGQL
      .send(JSON.stringify({query, variables}))

 

Tolulope_Akinol
Shopify Partner
25 1 1

Never mind.  The issue was that I was reusing the same request over iterations so the parameters of the very first request would carry over to all the subsequent ones.  I solved the problem by creating a new request each time