packages/inferencer/src/use-infer-fetch/index.tsx
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,
};
};