我试图 Package useQuery以集中使用它。然而,我遇到的问题是queryFn是在运行时构建的,所以当 Package 在我的自定义钩子中时,我必须根据queryFn是否准备好有条件地返回钩子的promise。这打破了钩子的规则。有人知道如何在我的自定义钩子中正确 Package useQuery吗?当前状态下的代码如下。要查看的主要部分是返回值以及如何设置queryFn。这就是问题的症结所在。
import {
QueryFunction,
QueryKey,
UseQueryOptions,
UseQueryResult,
useQuery,
} from "@tanstack/react-query";
import { AxiosRequestConfig, AxiosResponse } from "axios";
import {
ApiQueryConfig,
QueryPathParamsType,
QueryReturnType,
QueryUrlParamsType,
useApiClient,
} from "@api";
import { combineQueryKey } from "./utils";
import { useEffect, useState } from "react";
const useApiQuery = <
T extends ApiQueryConfig<any, Record<string, string>, Record<string, any>>,
ReturnType extends QueryReturnType<T>,
PathParamsType extends QueryPathParamsType<T>,
UrlParamsType extends QueryUrlParamsType<T>
>(
apiQueryConfig: ApiQueryConfig<ReturnType, PathParamsType, UrlParamsType>,
pathParams?: PathParamsType,
urlParams?: UrlParamsType,
axiosRequestConfig?: AxiosRequestConfig,
tanstackConfig?: UseQueryOptions<
AxiosResponse<ReturnType>,
Error,
AxiosResponse<ReturnType>,
QueryKey
>
): UseQueryResult<AxiosResponse<ReturnType, any>, Error> => {
const apiClient = useApiClient();
const [queryFn, setQueryFn] = useState<
QueryFunction<AxiosResponse<ReturnType, any>> | undefined
>(undefined);
const axiosConfigNonOverridable = {
params: urlParams || {},
};
const axiosConfigOverridable: AxiosRequestConfig = {
timeout: 10 * 1000,
};
const mergedAxiosRequestConfig: AxiosRequestConfig = {
...axiosConfigOverridable,
...(axiosRequestConfig || {}),
...axiosConfigNonOverridable,
};
const tanstackConfigNonOverridable: typeof tanstackConfig = {
enabled: !!apiClient && (tanstackConfig?.enabled || true),
};
const tanstackConfigOverridable: typeof tanstackConfig = {
networkMode: "online",
retry: 2,
retryOnMount: true,
staleTime: Infinity,
cacheTime: 10 * 60 * 1000,
refetchOnMount: true,
refetchOnWindowFocus: false,
refetchOnReconnect: true,
};
const mergedTanstackConfig: typeof tanstackConfig = {
...tanstackConfigOverridable,
...(tanstackConfig || {}),
...tanstackConfigNonOverridable,
};
const path = pathParams
? Object.entries(pathParams).reduce(
(accPath, [key, value]) => accPath.replace(`{${key}}`, value),
apiQueryConfig.apiPath
)
: apiQueryConfig.apiPath;
const queryKey = combineQueryKey(
apiQueryConfig.queryKey.baseQueryKey,
{ ...pathParams, ...urlParams },
apiQueryConfig.queryKey.dynamicQueryKey
);
useEffect(() => {
if (apiClient) {
console.log(apiClient);
setQueryFn(() => apiClient!.get(path, mergedAxiosRequestConfig));
}
// We should not use exhaustive deps here. Deps should be intentional.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [apiClient]);
if (!queryFn) {
return { isLoading: true } as UseQueryResult<
AxiosResponse<ReturnType, any>,
Error
>;
}
return useQuery<AxiosResponse<ReturnType>, Error>(
queryKey,
queryFn!,
mergedTanstackConfig
);
};
export { useApiQuery };
字符串
1条答案
按热度按时间sczxawaw1#
我同意@kca的评论,你应该考虑使用多个更小的钩子。返回“nothing”的方法是设置
enable: true
。我做了一些修改建议。最值得注意的是,我用一个常量替换了
queryFn
状态,并将enabled: false
设置为queryFn === undefined
。字符串