Search code examples
paginationgraphqlmaterial-uiapollo-clientmaterial-table

How to load more data when user scrolls in material UI table


I am making a GraphQL query to load Data in my Material UI table. I want it to load more data on scrolling.

The data is populated in the table correctly, the pagination stuff is not working correctly.

  return (
    <Query
      query={MESSAGE_QUERY}
      variables={{
        where: getQueryVariables({
          date,
        }),
        limit: 50,
        offset: 0,
        sortingOrder,
      }}
      fetchPolicy="cache-and-network"
    >
      {({ data, fetchMore }: QueryResult) => {
        fetchMore({
          variables: {
            offset: data.message
              ? data.message.length
              : 0,
          },
          updateQuery: (
            prevResult: { DataRowProps: any },
            { fetchMoreResult }: any,
          ) => {
            if (!fetchMoreResult) return prevResult;
            return Object.assign({}, prevResult, {
              ...fetchMoreResult.DataRowProps,
            });
          },
        });
        return data.message
          ? data.message.map(
              (rowData: DataRowProps, index: number) => {
                return containmentDOMRect ? (
                  <VisibilitySensor
                    containment={containmentDOMRect.current || undefined}
                    onChange={isVisible =>
                      isVisible && index % LOAD_SIZE === 0 && index >= LOAD_SIZE
                        ? loadMoreData(index)
                        : undefined
                    }
                  >
                    <DataRowComponent
                      {...rowData}
                      index={index}
                      selectedRow={selectedRow}
                      callBack={callBack}
                    />
                  </VisibilitySensor>
                ) : null;
              },
            )
          : null;
      }}
    </Query>
  );
};

I don't see any errors while running the code but it is not loading more data on scroll. I have removed some unimportant code because the stack overflow restrictions, let me know if that needs to be provided. Any help is highly appreciated.


Solution

  • The correct way to use the fecthMore and update query functions is inside VisibilitySensor tag:

          {({ data, fetchMore }: QueryResult) => {
        return data.vitm_truck_message
          ? data.vitm_truck_message.map(
              (rowData: DataRowProps, index: number) => {
                const visibilitySensorKey = rowData.message_type.name
                  .concat(rowData.message_sub_type.name)
                  .concat(rowData.created_time);
                return containmentDOMRect ? (
                  <VisibilitySensor
                    key={visibilitySensorKey}
                    containment={containmentDOMRect.current || undefined}
                    scrollCheck
                    onChange={isVisible =>
                      isVisible && index % LOAD_SIZE === 0 && index >= LOAD_SIZE
                        ? fetchMore({
                            variables: {
                              offset: data.vitm_truck_message
                                ? data.vitm_truck_message.length
                                : 0,
                            },
                            updateQuery: (
                              prev: any,
                              { fetchMoreResult }: any,
                            ) => {
                              if (
                                fetchMoreResult.vitm_truck_message.length !== 0
                              ) {
                                offsetValue = data.vitm_truck_message.length;
                                prev.vitm_truck_message.forEach(
                                  (element: object) => {
                                    if (
                                      data.vitm_truck_message.indexOf(element) <
                                      0
                                    ) {
                                      data.vitm_truck_message.push(element);
                                    }
                                  },
                                );
                                fetchMoreResult.vitm_truck_message.forEach(
                                  (element: object) => {
                                    if (
                                      data.vitm_truck_message.indexOf(element) <
                                      0
                                    ) {
                                      data.vitm_truck_message.push(element);
                                    }
                                  },
                                );
                              }
                              return prev;
                            },
                          })
                        : undefined
                    }
                  >
                    <DataRowComponent
                      {...rowData}
                      index={index}
                      selectedRow={selectedRow}
                      callBack={callBack}
                    />
                  </VisibilitySensor>
                ) : null;
              },
            )
          : null;
      }}