pankod/refine

View on GitHub
packages/inferencer/src/use-infer-fetch/index.tsx

Summary

Maintainability
C
1 day
Test Coverage
import React from "react";
import { useDataProvider, useResource, BaseKey } from "@refinedev/core";

import { pickDataProvider, dataProviderFromResource } from "../utilities";
import { InferencerComponentProps } from "../types";
import { pickMeta } from "../utilities/get-meta-props";

/**
 * This hook will handle the data fetching for the inferencer with `loading` and `initial` states.
 * Data provider functions will be used respectively for the `list`, `show` and `edit` types.
 */
export const useInferFetch = (
  type: "list" | "show" | "edit" | "create",
  resourceNameOrRouteName?: string,
  idFromProps?: string | number,
  meta?: InferencerComponentProps["meta"],
) => {
  const {
    resource,
    id: idFromURL,
    resources,
  } = useResource(resourceNameOrRouteName);

  const id = idFromProps ?? idFromURL;

  const dataProvider = useDataProvider();

  const [error, setError] = React.useState<string | undefined>(undefined);

  const [data, setData] = React.useState<Record<string, unknown> | undefined>(
    undefined,
  );
  const [datas, setDatas] = React.useState<
    Array<Record<string, unknown>> | undefined
  >(undefined);
  const [initial, setInitial] = React.useState<boolean>(true);
  const [loading, setLoading] = React.useState<boolean>(false);

  const resolver = React.useCallback(
    async (recordItemId: BaseKey | undefined) => {
      const dataProviderName =
        dataProviderFromResource(resource) ??
        pickDataProvider(resource?.name, undefined, resources);
      const dp = dataProvider(dataProviderName);

      setLoading(true);
      setError(undefined);

      try {
        if (type === "list" || type === "create") {
          if (resource) {
            const response = await dp.getList({
              resource: resource?.name,
              meta: pickMeta(resource?.identifier ?? resource?.name, meta, [
                "getList",
              ]),
            });
            const r = response.data?.[0];

            if (!r) {
              setError(
                `<p>No records/data found for resource "${resource?.name}".</p>
                            <p>Please check your data provider and resource.</p>
                            <p>For more info, please check the <a href="https://refine.dev/docs/packages/documentation/inferencer/" target="_blank">documentation</a>.</p>`,
              );
            }
            setData(r);
            setDatas(response.data);
            setTimeout(() => {
              setLoading(false);
            }, 500);
          }
        }
        if ((type === "edit" || type === "show") && recordItemId) {
          if (resource) {
            const response = await dp.getOne({
              resource: resource?.name,
              id: recordItemId,
              meta: pickMeta(resource?.identifier ?? resource?.name, meta, [
                "getOne",
              ]),
            });
            const r = response.data;
            if (!r) {
              setError(
                `<p>No records/data found for resource "${resource?.name}".</p>
                            <p>Please check your data provider and resource.</p>
                            <p>For more info, please check the <a href="https://refine.dev/docs/packages/documentation/inferencer/" target="_blank">documentation</a>.</p>`,
              );
            }
            setData(r);
            setTimeout(() => {
              setLoading(false);
            }, 500);
          }
        }
      } catch (error) {
        console.warn(
          "An error occured while fetching the resource data. Please check the error message below:",
          error,
        );
        setError(
          `<p>Something went wrong while fetching the resource data.</p>
                    <p>Please check your data provider and API for resource "${resource?.name}".</p>
                    <p>For more info, please check the <a href="https://refine.dev/docs/packages/documentation/inferencer/" target="_blank">documentation</a>.</p>`,
        );
        setTimeout(() => {
          setLoading(false);
        }, 500);
      }
    },
    [type, dataProvider, resource, resources],
  );

  React.useEffect(() => {
    setInitial(false);
    if (!loading && !data) {
      resolver(id);
    }
  }, [resolver, id]);

  return {
    data,
    datas,
    loading,
    initial,
    error,
  };
};