pankod/refine

View on GitHub
packages/core/src/hooks/show/index.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import warnOnce from "warn-once";
import { useMeta, useOne, useResourceParams, useLoadingOvertime } from "@hooks";
import { pickNotDeprecated } from "@definitions/helpers";

import type { UseShowProps, UseShowReturnType } from "./types";
import { BaseKey, BaseRecord, HttpError } from "../../contexts/data/types";

export type {
  UseShowProps,
  UseShowReturnType,
  useShowProps,
  useShowReturnType,
} from "./types";

/**
 * `useShow` hook allows you to fetch the desired record.
 * It uses `getOne` method as query function from the dataProvider that is
 * passed to {@link https://refine.dev/docs/core/refine-component `<Refine>`}.
 *
 * @see {@link https://refine.dev/docs/data/hooks/use-show} for more details.
 *
 * @typeParam TQueryFnData - Result data returned by the query function. Extends {@link https://refine.dev/docs/core/interface-references/#baserecord `BaseRecord`}
 * @typeParam TError - Custom error object that extends {@link https://refine.dev/docs/core/interface-references/#httperror `HttpError`}
 * @typeParam TData - Result data returned by the `select` function. Extends {@link https://refine.dev/docs/core/interface-references/#baserecord `BaseRecord`}. Defaults to `TQueryFnData`
 *
 */
export const useShow = <
  TQueryFnData extends BaseRecord = BaseRecord,
  TError extends HttpError = HttpError,
  TData extends BaseRecord = TQueryFnData,
>({
  resource: resourceFromProp,
  id,
  meta,
  metaData,
  queryOptions,
  overtimeOptions,
  ...useOneProps
}: UseShowProps<TQueryFnData, TError, TData> = {}): UseShowReturnType<
  TData,
  TError
> => {
  const {
    resource,
    identifier,
    id: showId,
    setId: setShowId,
  } = useResourceParams({
    id,
    resource: resourceFromProp,
  });

  const getMeta = useMeta();

  const combinedMeta = getMeta({
    resource,
    meta: pickNotDeprecated(meta, metaData),
  });

  warnOnce(
    Boolean(resourceFromProp) && !showId,
    idWarningMessage(identifier, showId),
  );

  const queryResult = useOne<TQueryFnData, TError, TData>({
    resource: identifier,
    id: showId ?? "",
    queryOptions: {
      enabled: showId !== undefined,
      ...queryOptions,
    },
    meta: combinedMeta,
    metaData: combinedMeta,
    ...useOneProps,
  });

  const { elapsedTime } = useLoadingOvertime({
    isLoading: queryResult.isFetching,
    interval: overtimeOptions?.interval,
    onInterval: overtimeOptions?.onInterval,
  });

  return {
    queryResult,
    showId,
    setShowId,
    overtime: { elapsedTime },
  };
};

const idWarningMessage = (identifier?: string, id?: BaseKey) =>
  `[useShow]: resource: "${identifier}", id: ${id} \n\nIf you don't use the \`setShowId\` method to set the \`showId\`, you should pass the \`id\` prop to \`useShow\`. Otherwise, \`useShow\` will not be able to infer the \`id\` from the current URL. \n\nSee https://refine.dev/docs/data/hooks/use-show/#resource`;