我的项目中的许多查询都采用相同的参数,它是一个仪表板应用程序。我正在尝试构建一个包装器,这样我就不必不断从上下文中获取这些参数。
我现在正在尝试的代码是
interface IUseLazyQuery {
<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>(
queryKey: TQueryKey,
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
options?: Omit<
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
"queryKey" | "queryFn" | "initialData"
> & {
initialData?: () => undefined;
}
): ReturnType<typeof useQuery<TData, TError>> & {
fetch: Function;
};
}
type IUseLazyQueryOptions<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
> = Omit<
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
"queryKey" | "queryFn" | "initialData"
> & {
initialData?: () => undefined;
};
export const useLazyQuery: IUseLazyQuery = <
TQueryKey extends QueryKey,
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData
>(
queryKey: TQueryKey,
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
options?: IUseLazyQueryOptions<TQueryFnData, TError, TData, TQueryKey>
) => {
const [enabled, setEnabled] = useState(false);
const resolveRef = useRef<(value: unknown) => void>();
const query = useQuery(queryKey, queryFn, {
...options,
enabled: enabled && (options?.enabled === undefined || options?.enabled),
onSettled: () => {
if (resolveRef.current) {
resolveRef.current(null);
resolveRef.current = undefined;
}
},
});
useEffect(() => {
setEnabled(false);
}, [query.data]);
return {
fetch: () => {
setEnabled(true);
return new Promise(async (resolve) => {
resolveRef.current = resolve;
while (resolveRef.current) {
await new Promise((resolve) => setTimeout(resolve, 500));
}
});
},
...query,
};
};
export const useFilteredRequest = <
TQueryFuncParams extends object,
TQueryKey extends QueryKey = QueryKey,
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData
>(
name: string,
func: (params: TQueryFuncParams) => TQueryFnData,
params: TQueryFuncParams,
options: IUseLazyQueryOptions<TQueryFnData, TError, TData, TQueryKey>
) => {
const { category, classification, selectedBrands } = usePageFilters();
const { filterRequestParams } = useFilterContext();
const { dataFinalStr, dataInicialStr } = useDateFilterContext();
const filterParams = useMemo(() => {
return {
marcas: selectedBrands.join(","),
classificacoes: classification,
categorias: category,
data_final: dataFinalStr,
data_inicio: dataInicialStr,
...filterRequestParams,
};
}, [
selectedBrands,
classification,
category,
dataFinalStr,
dataInicialStr,
filterRequestParams,
]);
const queryFuncParams = useMemo(() => {
return { ...params, ...filterParams };
}, [params, filterParams]);
return useLazyQuery(
[name, ...Object.values(queryFuncParams).sort()],
() => func(queryFuncParams),
options
);
};
我遇到类型错误:
Argument of type '(string | null | undefined)[]' is not assignable to parameter of type 'TQueryKey'.
'(string | null | undefined)[]' is assignable to the constraint of type 'TQueryKey', but 'TQueryKey' could be instantiated with a different subtype of constraint 'readonly unknown[]'
开
return useLazyQuery(
[name, ...Object.values(queryFuncParams).sort()],
() => func(queryFuncParams),
options
);
[name, ...Object.values(queryFuncParams).sort()]
解析为 (string | null | undefined)[]
但不知怎的,这与readonlyknown[]
尝试更改 TQueryKey 类型,但没有任何效果
最佳答案
这就是为什么我总是建议不要在 useQuery 上构建如此低级的抽象。 useLazyQuery
包装器很好,对于 useFilteredRequest
,您无法从外部提供 TQueryKey
的泛型,因为它可以被任意实例化。函数 useFilteredRequest
本身创建了 QueryKey,因此类型相对固定,但是,您仍然需要将该类型提供给 QueryOptions:
- options?: IUseLazyQueryOptions<TQueryFnData, TError, TData, TQueryKey>
+ options?: IUseLazyQueryOptions<TQueryFnData, TError, TData, (string | null | undefined)[]>
关于reactjs - useQuery 包装器查询键类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75023261/