All files / src/hooks/common useGetInfiniteList.tsx

90.47% Statements 19/21
66.66% Branches 12/18
100% Functions 5/5
95% Lines 19/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                                                  27x   27x         844x                               844x           909x         844x                                     27x 118x 118x 118x 118x             27x 844x 118x 118x         118x   118x         114x   114x            
import { UseInfiniteQueryOptions, useInfiniteQuery } from "react-query";
import { queryGenerator } from "@utils/generators/queryGenerator";
import { customInstance } from "@services/api";
 
type TParamValueLiteral = string | number;
type TParamValueComposed = TParamValueLiteral | null | Record<string, any>;
 
type TQueryParams = {
  sort?: string;
  filter?: TParamValueComposed;
  q?: string;
  max?: TParamValueLiteral;
};
 
type TConfig = {
  queryKey: string;
  baseURL: string;
  dependencies?: (string | number)[];
};
 
type TQueryOptions = Omit<
  UseInfiniteQueryOptions<any, unknown, any, any, any>,
  "queryKey" | "queryFn"
>;
 
const DEFAULT_PAGE_ELEMENT_NUMBER = 20;
 
const useGetInfiniteList = (
  queryParams: TQueryParams,
  config: TConfig,
  queryOptions?: TQueryOptions,
) => {
  const { queryKey, baseURL, dependencies = [] } = config;
 
  const {
    status,
    data,
    error,
    isFetching,
    isFetchingNextPage,
    isFetchingPreviousPage,
    fetchNextPage,
    fetchPreviousPage,
    hasNextPage,
    hasPreviousPage,
    isLoading,
    remove,
    refetch,
  } = useInfiniteQuery(
    [queryKey, ...dependencies],
    queryBuilder(baseURL, queryParams),
    {
      ...queryOptions,
      getNextPageParam: (lastPage: any) => {
        return lastPage.nextCursor;
      },
    },
  );
 
  return {
    status,
    data,
    error,
    isFetching,
    isFetchingNextPage,
    isFetchingPreviousPage,
    isLoading,
    fetchNextPage,
    fetchPreviousPage,
    hasNextPage,
    hasPreviousPage,
    remove,
    refetch,
  };
};
 
export default useGetInfiniteList;
 
const getElementsPerPage = (max?: TParamValueLiteral) => {
  Iif (!max) return DEFAULT_PAGE_ELEMENT_NUMBER;
  try {
    const parsedMax = typeof max === "number" ? max : parseInt(max);
    return Number.isNaN(parsedMax) ? DEFAULT_PAGE_ELEMENT_NUMBER : parsedMax;
  } catch (err) {
    return DEFAULT_PAGE_ELEMENT_NUMBER;
  }
};
 
const queryBuilder =
  (baseURL: string, queryParams: TQueryParams) =>
  async ({ pageParam = 1 }) => {
    const elementsPerPage = getElementsPerPage(queryParams?.max);
    const paramsWithDefaults = {
      ...queryParams,
      max: elementsPerPage,
      page: pageParam ?? 1,
    };
    const encodedURL = queryGenerator(baseURL, paramsWithDefaults);
 
    const data = await customInstance({
      url: encodedURL,
      method: "GET",
    });
 
    const numberOfPages = Math.ceil(Number(data.total ?? 0) / elementsPerPage);
 
    return {
      data: data?.data || [],
      nextCursor: numberOfPages >= pageParam + 1 ? pageParam + 1 : null,
      total: data?.total || 0,
    };
  };