Pagination with Query react-apollo & GraphQL

Highlighted
Tourist
5 0 0

I'm trying to use apollo fetchMore to fetch paginated results from the graphQL endpoint. Here is what I've got so far. It does the first query successfully, but it does not try to load additional pages. Any ideas on what I'm doing wrong?

 

import gql from "graphql-tag";
import { Query } from "react-apollo";
import { Page } from "@shopify/polaris";

const GET_PRODUCTS = gql`
  query getProducts($cursor: String) {
    products(first: 1, after: $cursor) {
      pageInfo {
        hasNextPage
      }
      edges {
        node {
          id
          title
          descriptionHtml
        }
        cursor
      }
    }
  }
`;

class Index extends React.Component {
  state = {
    products: []
  };

  render() {
    return (
      <Page>
        <Query query={GET_PRODUCTS}>
          {({ data, loading, error, fetchMore }) => {
            <getProducts
              onLoadMore={() => {
                console.log("LOAD MORE");
                fetchMore({
                  variables: {
                    cursor: data.products.edges[0].cursor
                  },
                  updateQuery: (previousResult, { fetchMoreResult }) => {
                    console.log("FETCH MORE RESULTS", fetchMoreResult);
                    if (fetchMoreResult.products.edges.length) {
                      return [
                        ...previousResult.products.edges,
                        ...fetchMoreResults.products.edges
                      ];
                    }
                    return previousResult.products.edges;
                  }
                });
              }}
            />;
            if (loading) return <div>loading products to memory...</div>;
            if (error) return <div>{error.message}</div>;
            return <div>success!</div>;
          }}
        </Query>
      </Page>
    );
  }
}

export default Index;
0 Likes
Highlighted
Tourist
5 0 0

Alright, I re-worked the Query component and seem to have it working. Is there a better way to do this?

 

<Query query={GET_PRODUCTS}>
          {({ data, loading, error, fetchMore }) => {
            if (loading) return <div>loading products to memory...</div>;
            if (error) return <div>{error.message}</div>;
            if (data.products.pageInfo.hasNextPage) {
              fetchMore({
                variables: {
                  cursor:
                    data.products.edges[data.products.edges.length - 1].cursor
                },
                updateQuery: (previousResult, { fetchMoreResult }) => {
                  let combinedData = {
                    products: {
                      pageInfo: { ...fetchMoreResult.products.pageInfo },
                      edges: [
                        ...previousResult.products.edges,
                        ...fetchMoreResult.products.edges
                      ],
                      __typename: fetchMoreResult.products.__typename
                    }
                  };
                  return combinedData;
                }
              });
            }
            console.log("HERE", data);
            return <div>{JSON.stringify(data)}</div>;
          }}
        </Query>
0 Likes
Highlighted
Pathfinder
83 4 9

@find-replace I'm having trouble at this same point and haven't been able to get fetchMore working. Did you ever work out a better solution? 

0 Likes
Highlighted
Tourist
5 0 0

I ended up with this which works fine.

<Query query={GET_PRODUCTS}>
                {({ data, loading, error, fetchMore, refetch }) => {
                  if (loading) return <Loading />;
                  if (error) {
                    console.log("ERROR", error);
                    return <div>{error.message}</div>;
                  }

                  if (data.products.pageInfo.hasNextPage) {
                    fetchMore({
                      variables: {
                        cursor:
                          data.products.edges[data.products.edges.length - 1]
                            .cursor
                      },
                      updateQuery: (previousResult, { fetchMoreResult }) => {
                        console.log("FETCH MORE", data.products.pageInfo);
                        return {
                          products: {
                            pageInfo: {
                              ...fetchMoreResult.products.pageInfo
                            },
                            edges: [
                              ...previousResult.products.edges,
                              ...fetchMoreResult.products.edges
                            ],
                            __typename: fetchMoreResult.products.__typename
                          }
                        };
                      }
                    });
                  }

                  if (!data.products.pageInfo.hasNextPage) {
                    console.log("DONE", data.products.pageInfo);
                    return (
                      <Find products={data.products.edges} refetch={refetch}>
                        Done
                      </Find>
                    );
                  }

                  return <Loading />;
                }}
              </Query>
0 Likes