reactjs - useQuery 包装器查询键类型不匹配

标签 reactjs typescript react-query

我的项目中的许多查询都采用相同的参数,它是一个仪表板应用程序。我正在尝试构建一个包装器,这样我就不必不断从上下文中获取这些参数。

我现在正在尝试的代码是

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)[]>

这是一个working TypeScript playground

关于reactjs - useQuery 包装器查询键类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75023261/

相关文章:

javascript - 我的 reducer 返回 undefined 就像它没有被添加到 combineReducers 中一样,但它是

javascript - 如何定义或让 Typescript 忽略相关环境模块?

reactjs - React-query mutateAsync 中的错误处理

reactjs - 如何使用 React-Query 处理多个查询

reactjs - 在 React + TypeScript 中从类组件传递 props

javascript - react : Trying to render props that populate AFTER render

javascript - Reactjs - 根据条件渲染标签

javascript - 如何在 Angular 7 中配置 raw-loader 来加载文本文件?

reactjs - 在 typescript 中将 useState 作为 props 传递

reactjs - 如何让Query在组件onmount时执行,并在稍后由用户事件触发?