@rocketmakers/api-swr
Version:
Rocketmakers front-end library for parsing a generated Typescript API client into a set of configurable React hooks for fetching and mutating data.
47 lines (46 loc) • 3.84 kB
JavaScript
'use client';
/*
* React hook for querying data on the client
* --------------------------------------
* Wraps the SWR hook, see here: https://swr.vercel.app
*/
import * as React from 'react';
import useSwrInfinite from 'swr/infinite';
import { readCacheKey } from '../utils/caching';
import { useClientFetch } from './useClientFetch';
import { useContentMemo } from './useContentMemo';
/**
* A wrapper around the `useSwrInfinite` hook that includes a custom `fetch` function, `cacheKey` generator and SWR config.
* @template TFunc - A function that returns a Promise with some data from the API.
* @template TConfig - A configuration object to be passed to the fetch function.
* @param {string} endpointId - The `controller.endpoint` ID
* @param {TFunc} fetcher - The function to use for fetching data.
* @param {IUseQueryInfiniteConfig<TFunc, TConfig>} hookConfig - An object containing the `cacheKey`, `params`, `config` and `swrConfig` options.
* @param {APIProcessingHook} useProcessing - An optional API processing hook to render.
* @param {GlobalFetchWrapperHook<TConfig>} useGlobalFetchWrapper - An optional fetch wrapper hook to render.
* @param {SWRInfiniteConfiguration<unknown | undefined>} globalSwrInfiniteConfig - Global level infinite SWR config.
* @returns {IUseInfiniteQueryResponse<TFunc, TProcessingResponse>} - The response from the `useSwrInfinite` hook augmented with the error and processing response.
*/
export const useInfiniteQuery = (endpointId, fetcher, hookConfig, useProcessing, useGlobalFetchWrapper, globalSwrInfiniteConfig) => {
/** Used to fetch data on the client, calls the root fetcher with the params and config passed into the hook */
const { clientFetch, error, processingResponse } = useClientFetch(endpointId, 'query', hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.fetchConfig, fetcher, undefined, useProcessing, useGlobalFetchWrapper, hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.fetchWrapper);
/** Content memo on the swr config to avoid dependency changes in SWR */
const swrConfig = useContentMemo(hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.swrConfig);
/** Content memo on the global swr config to avoid dependency changes in SWR */
const globalSwrConfigMemo = useContentMemo(globalSwrInfiniteConfig);
/** Reads the cacheKey value from the cacheKey definition sent to the hook, appending the params so that they can be read back when fetching */
const cacheKeyValue = React.useCallback((index, prevData) => {
var _a;
const finalParams = (_a = hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.params) === null || _a === void 0 ? void 0 : _a.call(hookConfig, index, prevData);
return [readCacheKey(endpointId, hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.cacheKey, finalParams), finalParams];
}, [hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.cacheKey, hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.params, endpointId]);
/** Protect the root fetcher from causing dependency changes in SWR */
const rootFetch = React.useCallback(async (key) => {
return clientFetch(key[1]);
}, [clientFetch, hookConfig === null || hookConfig === void 0 ? void 0 : hookConfig.params]);
/** Protect the combined SWR config from causing dependency changes in SWR */
const combinedSwrConfig = React.useMemo(() => (Object.assign(Object.assign({}, globalSwrConfigMemo), swrConfig)), [globalSwrConfigMemo, swrConfig]);
/** Returns the native useSwrInfinite hook from the SWR library, see here: https://swr.vercel.app */
return Object.assign(Object.assign({}, useSwrInfinite(cacheKeyValue, rootFetch, combinedSwrConfig)), { error,
processingResponse });
};