0

I'm using React with @tanstack/react-table and react-query to implement a paginated table with server-side filtering and sorting. I'm encountering an issue where selecting a date filter sometimes causes the table to display an incorrect or empty page and also triggers redundant API calls when the datepicker is opened or closed.

I have a separate state of 'pageIndex' that is sent to the database for filter operations. When I select a date, I set the 'pageIndex' to 0, but as per my observation, it again sets the 'pageIndex' to the previous pageIndex, which causes a redundant API call.

The state and functions are:

  const [pageIndex, setPageIndex] = useState<number>(0);
  const [pageCount, setPageCount] = useState<number>(0);
  const [pageSize, setPageSize] = useState<number>(5);
  const [totalRows, setTotalRows] = useState<number>(0);
  const [searchQuery, setSearchQuery] = useState<string>('');
  const [sorting, setSorting] = useState<SortingState>([]);
  const [selectedDate, setSelectedDate] = useState<Date | null>(null);

    const fetchPackageDetails = async (params: object) => {
    try {
      let startDate, endDate;
      if (selectedDate) {
        const { start, end } = convertToUTCStartAndEnd(selectedDate);
        startDate = start;
        endDate = end;
      }

      const response = await getPaginatedPackageDetails({
        ...params,
        startDate,
        endDate,
      });

      if (response.status === 200 || response.status === 204) {
        return response;
      }
    } catch (error) {
      console.log('Error while fetching package details: ', error);
    }
  };

    const handlePaginationChange = (pagination: {
    pageSize: number;
    pageIndex: number;
  }) => {
    console.log(
      'Changing pageiNdex in handlePaginationChange: ',
      pageIndex,
      pagination.pageIndex,
    );
    setPageSize(pagination.pageSize);
    setPageIndex(pagination.pageIndex);
  };

  const handleSortingChange = (newSorting: SortingState) => {
    setSorting(newSorting);
  };

  const {
    data: bookings,
    isLoading,
    isSuccess,
    isError,
  } = useQuery({
    queryKey: [
      'bookingList',
      { pageSize, pageIndex, searchQuery, sorting, selectedDate },
    ],
    staleTime: 1000 * 60 * 2,
    retry: 1,
    retryDelay: 1000,
    queryFn: async () => {
      const params: FetchParams = {
        pageSize,
        pageIndex,
        searchQuery,
        sortField: sorting[0]?.id || '',
        sortOrder: sorting[0]?.desc ? 'desc' : 'asc',
      };
      if (activeTab === 'package') {
        return await fetchPackageDetails(params);
      } else {
        // return await fetchSessionDetails(params);
      }
    },
  });

  useEffect(() => {
    if (isSuccess && !isLoading) {
      if (activeTab === 'package') {
        setPackageDetails(bookings?.data?.data);
      } else if (activeTab === 'session') {
        setSessionDetails(bookings?.data?.data);
      }

      // Only update these values, remove setPageIndex
      setPageCount(bookings?.data?.pageCount);
      setTotalRows(bookings?.data?.totalRows);
    }
  }, [isSuccess, bookings, isLoading, activeTab]);

Example usage:

<div className="flex md:justify-normal gap-3 justify-between items-center">
        <div className="relative inline-block">
          <DatePicker
            selected={selectedDate}
            onChange={handleDateChange}
            placeholderText="Filter by: Date"
            className="border text-[14px] border-[#D9D9D9] rounded-t-[15px] rounded-b-none px-4 py-1.5 rounded"
            open={isDatePickerOpen}
            onCalendarOpen={() => setIsDatePickerOpen(true)}
            onCalendarClose={() => setIsDatePickerOpen(false)}
            customInput={<CustomInput />}
            popperClassName="left-0 right-0 md:!-left-[30px]"
          />
        </div>
      </div>
      <div className="mt-4">
        <ServerDataTable
          data={getActiveTab()}
          columns={packageDetailsCols}
          noDataText="No packages found"
          pageCount={pageCount}
          pageIndex={pageIndex}
          pageSize={pageSize}
          onPaginationChange={handlePaginationChange}
          isLoading={isLoading}
          totalRows={totalRows}
          onSortingChange={handleSortingChange}
        />
      </div>

Redundant API calls:

First API call after I change the date, which returns the actual data which is required

Second unnecessary API call, in which 'pageIndex' is sent as '1' and I dont know 1

Also, I have noticed that when I open and close the date picker, the handlePaginationChange is getting triggered.

1 Answer 1

0

Have you try to use "enabled" option of "useQuery"? It is only fetch data when meet certain condition and prevent redundant API call.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.