Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
323 views
in Technique[技术] by (71.8m points)

GraphQL - Apollo Client 3 | Pagination

I'm new to Apollo Client and I'm trying to wrap my head around field policies to implement pagination. So basically I have a category page where I perform a query that is based on the the slug that I receive from the URL of the page, returns a list of IDs (and I pass them down as props for the product component), for example:

query getProductId($slug: String!) {
  slug(where: {slug: $slug}){
    products {
      Id
    }
  }
}

from this query I get and array of all the objects containing the IDs of the products.
I can pass a "first: " and "after: {id: }" to the products field and this way I could decide after which product ID I want to query. for example:

query getProductId($slug: String!) {
  slug(where: {slug: $slug}){
    products(first: 4, after: {id: 19}) {
      Id
    }
  }
}

I know that in my ApolloClient instance I can define a field policy for the cache like this:

const apollo = new ApolloClient({
  //...
  cache: new InMemoryClient({
    typePolicies: {
      Query: {
        fields: {
         products: offsetLimitPagination(["<* keyArgs>"]),
        },
      },
    },
  })
})

This is just one random helper function I took, but in my case I think using a cursor based strategy is better since I could use the last ID in the list as cursor, I guess(?) From here I'm completely lost, the more I read the docs the more I get confused.

{
            keyArgs: ["first"],

            merge(existing, incoming, { args: { cursor }, readField }) {
              const merged = existing ? existing.slice(0) : [];
              let offset = offsetFromCursor(merged, cursor, readField);
              // If we couldn't find the cursor, default to appending to
              // the end of the list, so we don't lose any data.
              if (offset < 0) offset = merged.length;
              // Now that we have a reliable offset, the rest of this logic
              // is the same as in offsetLimitPagination.
              for (let i = 0; i < incoming.length; ++i) {
                merged[offset + i] = incoming[i];
              }
              return merged;
            },

            // // If you always want to return the whole list, you can omit
            // // this read function.
            // read(
            //   existing,
            //   { args: { cursor, limit = existing.length }, readField }
            // ) {
            //   if (existing) {
            //     let offset = offsetFromCursor(existing, cursor, readField);
            //     // If we couldn't find the cursor, default to reading the
            //     // entire list.
            //     if (offset < 0) offset = 0;
            //     return existing.slice(offset, offset + limit);
            //   }
            // },
          },
        },
      },
    },
  }),
});

function offsetFromCursor(items, cursor, readField) {
  // Search from the back of the list because the cursor we're
  // looking for is typically the ID of the last item.
  for (let i = items.length - 1; i >= 0; --i) {
    const item = items[i];
    // Using readField works for both non-normalized objects
    // (returning item.id) and normalized references (returning
    // the id field from the referenced entity object), so it's
    // a good idea to use readField when you're not sure what
    // kind of elements you're dealing with.
    if (readField("id", item) === cursor) {
      // Add one because the cursor identifies the item just
      // before the first item in the page we care about.
      return i + 1;
    }
  }
  // Report that the cursor could not be found.
  return -1;
}

Let's suppose I use this a field policy for the list of products, how do I go from here? I'm completely lost


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...