analytics/assets/js/dashboard/hooks/api-client.js

83 lines
2.7 KiB
JavaScript

import { useEffect } from "react"
import { useQueryClient, useInfiniteQuery } from "@tanstack/react-query"
import * as api from "../api"
const LIMIT = 100
/**
* A wrapper for the React Query library. Constructs the necessary options
* (including pagination config) to pass into the `useInfiniteQuery` hook.
*
* ### Required props
*
* @param {Array} key - The key under which the global "query" instance will live.
* Should be passed as a list of two elements - `[endpoint, { query }]`. The object
* can also contain additional values (such as `search`) to be used by:
* 1) React Query, to determine the uniqueness of the query instance
* 2) the `getRequestParams` function to build the request params.
*
* @param {Function} getRequestParams - A function that takes the `key` prop as an
* argument, and returns `[query, params]` which will be used by `queryFn` that
* actually calls the API.
*
* ### Optional props
*
* @param {Function} [afterFetchData] - A function to call after data has been fetched.
* Receives the API response as an argument.
*
* @param {Function} [afterFetchNextPage] - A function to call after the next page has
* been fetched. Receives the API response as an argument.
*/
export function useAPIClient(props) {
const {key, getRequestParams, afterFetchData, afterFetchNextPage} = props
const [endpoint] = key
const queryClient = useQueryClient()
const queryFn = async ({ pageParam, queryKey }) => {
const [query, params] = getRequestParams(queryKey)
params.limit = LIMIT
params.page = pageParam
const response = await api.get(endpoint, query, params)
if (pageParam === 1 && typeof afterFetchData === 'function') {
afterFetchData(response)
}
if (pageParam > 1 && typeof afterFetchNextPage === 'function') {
afterFetchNextPage(response)
}
return response.results
}
// During the cleanup phase, make sure only the first page of results
// is cached under any `queryKey` containing this endpoint.
useEffect(() => {
const key = [endpoint]
return () => {
queryClient.setQueriesData(key, (data) => {
if (data?.pages?.length) {
return {
pages: data.pages.slice(0, 1),
pageParams: data.pageParams.slice(0, 1),
}
}
})
}
}, [queryClient, endpoint])
const getNextPageParam = (lastPageResults, _, lastPageIndex) => {
return lastPageResults.length === LIMIT ? lastPageIndex + 1 : null
}
const defaultInitialPageParam = 1
const initialPageParam = props.initialPageParam === undefined ? defaultInitialPageParam : props.initialPageParam
return useInfiniteQuery({
queryKey: key,
queryFn,
getNextPageParam,
initialPageParam
})
}