Pagination with Query react-apollo & GraphQL

find-replace
Tourist
5 0 1

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
find-replace
Tourist
5 0 1

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
Jroyce1180
Pathfinder
85 4 14

@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
find-replace
Tourist
5 0 1

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