How to retain search results in a Material-Table across page changes in Next.js without reloading the table?

41 Views Asked by At

I am working on a fix for a Material Table in a Next.js application, and I want to be able to retain search results of even after i visit another page, I have tried using local state to store the search results but every time i visit the page the table re-renders and the data is refetched. What is the best approach here? This is the component:

  <MaterialTable
            tableRef={tableRef}
            title={
              <Text variant="hSmSemiBold" mt="20px">
                Customers
              </Text>
            }
            columns={[
              {
                title: <h6>Account Type</h6>,
                field: 'institution',
                cellStyle: {
                  maxWidth: '121px'
                },
                render: ({ institution }) => {
                  return institution ? (
                    <span className="text-warning">Institution</span>
                  ) : (
                    <span className="text-success">Individual</span>
                  );
                }
              },
              {
                title: <h6>Name</h6>,
                field: 'fullName',
                cellStyle: {
                  maxWidth: '165px',
                  textTransform: 'capitalize'
                },
                render: ({ institution, institutionName, fullName }: { [x: string]: any }) => {
                  return institution ? institutionName : fullName;
                }
              },
              {
                title: <h6>Aggregate Holdings</h6>,
                field: 'userUuid',
                cellStyle: {
                  maxWidth: '134px'
                },
                render: ({ userUuid }) => {
                  return `${aggregatedCurrencies[userUuid]?.symbol || '$'} ${formatAmount(
                    (anh ?? {})[userUuid || '']
                  )}`;
                }
              },
              {
                title: <h6>Personal Info</h6>,
                field: 'customerProgress',
                cellStyle: {
                  maxWidth: '146px'
                },
                render: ({
                  customerProgress: {
                    customerCreated: { state }
                  }
                }) => <CustomerStatus customerState={state} stage="customerCreated" />
              },
              {
                title: <h6>KYC status</h6>,
                field: 'customerProgress',
                cellStyle: {
                  maxWidth: '135px'
                },
                render: ({
                  customerProgress: {
                    kyc: { state }
                  }
                }) => <CustomerStatus customerState={state} stage="kyc" />
              },
              {
                title: <h6>AML</h6>,
                field: 'customerProgress',
                cellStyle: {
                  maxWidth: '110px'
                },
                render: ({
                  customerProgress: {
                    aml: { state }
                  }
                }) => <CustomerStatus customerState={state} stage="accreditation" />
              },
              {
                title: <h6>Accreditation</h6>,
                field: 'customerProgress',
                cellStyle: {
                  maxWidth: '151px'
                },
                render: ({
                  customerProgress: {
                    accreditation: { state }
                  }
                }) => <CustomerStatus customerState={state} stage="accreditation" />
              },
              {
                title: <h6>Assignee</h6>,
                field: 'assignedAgent',
                render: ({ assignedAgent, userUuid }) => (
                  <Assignee
                    key={userUuid}
                    assignedAgent={
                      customerAgents[userUuid as keyof typeof customerAgents]
                        ? customerAgents[userUuid as keyof typeof customerAgents]
                        : assignedAgent
                    }
                    userUuid={userUuid}
                  />
                ),
                cellStyle: {
                  padding: 0,
                  maxWidth: '163px'
                }
              },
              {
                title: <h6>Source</h6>,
                field: 'objectCreatedBy',
                cellStyle: {
                  maxWidth: '106px'
                }
              },
              {
                title: <h6>Action</h6>,
                field: 'userUuid',
                cellStyle: {
                  maxWidth: '333px'
                },
                sorting: false,
                render: ({ userUuid, email, firstName, customerCreated }) => {
                  const query = customerCreated ? { id: userUuid } : { name: firstName, email };
                  return (
                    <Flex>
                      <Link
                        href={{ pathname: customerCreated ? 'customer' : 'create-customer', query }}
                        className="text-danger"
                      >
                        <Button size="xs">{customerCreated ? 'View' : 'Update Customer'}</Button>
                      </Link>
                      <CopyEmail size="xs" ml="10px" email={email} />
                    </Flex>
                  );
                }
              }
            ]}
            data={(query) => {
              const { pageSize, page, search, orderBy, orderDirection } = query;

              const url = `${endpoints.customers}?per_page=${pageSize === 5 ? 10 : pageSize}&page=${
                page + 1
              }&direction=${orderDirection}&search=${search.replace('+', '%2B')}&order_by=${
                orderBy?.field || ''
              }`;
              return new Promise((resolve) => {
                apiCall(METHOD_GET, activeFilter ? url + filterUrl : url, {}, {})
                  .then(({ data, page, totalCount }) => {
                    resolve({
                      data: data,
                      page: page - 1,
                      totalCount: totalCount
                    });
                  })
                  .catch(() => {
                    resolve({
                      data: [],
                      page: 0,
                      totalCount: 0
                    });
                  });
              });
            }}
            style={{
              boxShadow: 'drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.1))',
              backgroundColor: `${colors.defaultWhite}`,
              borderRadius: '8px'
            }}
            options={{
              thirdSortClick: false,
              search: true,
              pageSizeOptions: [10, 20, 50, 100],
              pageSize: 10,
              initialPage: 0,
              headerStyle: {
                color: `${colors.deepBlue}`,
                fontSize: '14px',
                fontWeight: 600
              },
              searchFieldStyle: {
                padding: '6px 12px',
                border: `1px solid ${colors.concrete}`,
                borderRadius: '4px'
              },
              rowStyle: {}
            }}
          />

I have tried to store the searchQuery results in local state and then add the data the data prop above but getting an error no overload matches this call. I was able to get the searchQuery and store the state of the data table but the search field is not able to maintain the state since the results of the lists are already paginated from the endpoints that return the data.
Also Material Table library forces a re-render every time the page is visited which re-fetches the data since we are using a custom query function on the same.

0

There are 0 best solutions below