diff --git a/README.md b/README.md
index 5ed302d..0168554 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ function AnotherExampleComponent () {
- returns a function that will return a queryToolkit instance
***
+
### createQuery
@@ -137,6 +138,8 @@ function AnotherExampleComponent () {
- Defaults to `'query'`
- if set to `'query'`, `QueryToolkit` will have `useQuery`, `fetchQuery`, `prefetchQuery` methods.
- if set to `'infiniteQuery'`, `QueryToolkit` will have `useInfiniteQuery`, `fetchInfiniteQuery`, `prefetchInfiniteQuery` methods.
+ - `defaultOptions: QueryOptions & UseQueryOptions & UseInfiniteQueryOptions`
+ - same option as react-query's query options [check out here](https://react-query.tanstack.com/reference/useQuery)
#### returns
@@ -144,6 +147,8 @@ function AnotherExampleComponent () {
- will Return a `QueryClient` instance
***
+
+
### createMutationToolkit
#### parameters
@@ -156,7 +161,12 @@ function AnotherExampleComponent () {
- `createMutaion: (queryKey, queryFn, options) => QueryToolkit`
- returns a function that will return a mutationToolkit instance
+
+***
+
+
### createMutation
+
#### parameters
- `mutationKey: MutationKey`
diff --git a/src/createMutationToolkit.ts b/src/createMutationToolkit.ts
index a2c341e..8cf03be 100644
--- a/src/createMutationToolkit.ts
+++ b/src/createMutationToolkit.ts
@@ -8,7 +8,7 @@ import {
} from "react-query";
import { MutationFilters } from "react-query/types/core/utils";
import { generateKey } from "./internal/generateKey";
-import { MutationToolkit } from "./types/mutation";
+import { MutationToolkit } from "./types/mutationToolkit";
export function createMutationToolkit(queryClient: QueryClient) {
function createMutation(
diff --git a/src/createQueryToolkit.ts b/src/createQueryToolkit.ts
index 81c062e..94350a0 100644
--- a/src/createQueryToolkit.ts
+++ b/src/createQueryToolkit.ts
@@ -8,36 +8,73 @@ import {
import { generateKey } from "./internal/generateKey";
import { returnByCondition } from "./internal/returnByCondition";
import {
- QueryToolkit,
- QueryToolkitInfiniteQueryType,
- QueryToolkitQueryType,
+ QueryDefaultOption,
QueryType,
TQueryFunction,
+ UseInfiniteQueryDefaultOption,
+ UseQueryDefaultOption,
} from "./types/query";
+import {
+ QueryToolkit,
+ QueryToolkitInfiniteQueryType,
+ QueryToolkitQueryType,
+} from "./types/queryToolkit";
export function createQueryToolkit(queryClient: QueryClient) {
- function createQuery(
+ function createQuery<
+ TQueryFnArgs extends unknown[],
+ TQueryFnReturn,
+ TData = TQueryFnReturn,
+ >(
queryKey: QueryKey,
queryFn: TQueryFunction,
- options?: { passArgsToQueryKey?: boolean; queryType?: "query" },
+ options?: {
+ passArgsToQueryKey?: boolean;
+ queryType?: "query";
+ defaultOptions?: QueryDefaultOption &
+ UseQueryDefaultOption;
+ },
): Omit<
- QueryToolkitQueryType,
+ QueryToolkitQueryType,
"useInfiniteQuery" | "fetchInfiniteQuery" | "prefetchInfiniteQuery"
>;
- function createQuery(
+ function createQuery<
+ TQueryFnArgs extends unknown[],
+ TQueryFnReturn,
+ TData = TQueryFnReturn,
+ >(
queryKey: QueryKey,
queryFn: TQueryFunction,
- options?: { passArgsToQueryKey?: boolean; queryType?: "infiniteQuery" },
+ options?: {
+ passArgsToQueryKey?: boolean;
+ queryType?: "infiniteQuery";
+ defaultOptions?: QueryDefaultOption &
+ UseInfiniteQueryDefaultOption;
+ },
): Omit<
- QueryToolkitInfiniteQueryType,
+ QueryToolkitInfiniteQueryType,
"useQuery" | "fetchQuery" | "prefetchQuery"
>;
- function createQuery(
+ function createQuery<
+ TQueryFnArgs extends unknown[],
+ TQueryFnReturn,
+ TData = TQueryFnReturn,
+ >(
queryKey: QueryKey,
queryFn: TQueryFunction,
- options: { passArgsToQueryKey?: boolean; queryType?: QueryType } = {},
+ options: {
+ passArgsToQueryKey?: boolean;
+ queryType?: QueryType;
+ defaultOptions?: QueryDefaultOption &
+ UseQueryDefaultOption &
+ UseInfiniteQueryDefaultOption;
+ } = {},
) {
- const { passArgsToQueryKey = true, queryType = "query" } = options;
+ const {
+ passArgsToQueryKey = true,
+ queryType = "query",
+ defaultOptions,
+ } = options;
const isInfiniteQuery = queryType === "infiniteQuery";
const returnOnQuery = returnByCondition(!isInfiniteQuery);
@@ -55,7 +92,7 @@ export function createQueryToolkit(queryClient: QueryClient) {
hook(
getKey(queryOptions?.queryKey, args),
queryFn(...((args || []) as TQueryFnArgs)),
- queryOptions,
+ { ...defaultOptions, ...queryOptions },
);
const hooks: Partial<
@@ -78,7 +115,7 @@ export function createQueryToolkit(queryClient: QueryClient) {
(queryClient as any)[path](
getKey(options?.queryKey, args),
queryFn(...args),
- options,
+ { ...defaultOptions, ...options },
),
);
@@ -110,12 +147,17 @@ export function createQueryToolkit(queryClient: QueryClient) {
if (isInfiniteQuery)
return handler as Omit<
- QueryToolkitInfiniteQueryType,
+ QueryToolkitInfiniteQueryType<
+ TQueryFnArgs,
+ TQueryFnReturn,
+ Error,
+ TData
+ >,
"useQuery" | "fetchQuery" | "prefetchQuery"
>;
return handler as Omit<
- QueryToolkitQueryType,
+ QueryToolkitQueryType,
"useInfiniteQuery" | "fetchInfiniteQuery" | "prefetchInfiniteQuery"
>;
}
diff --git a/src/types/mutation.ts b/src/types/mutationToolkit.ts
similarity index 100%
rename from src/types/mutation.ts
rename to src/types/mutationToolkit.ts
diff --git a/src/types/query.ts b/src/types/query.ts
index 4352c5a..6355ffd 100644
--- a/src/types/query.ts
+++ b/src/types/query.ts
@@ -1,128 +1,32 @@
import {
- CancelOptions,
- FetchInfiniteQueryOptions,
- FetchQueryOptions,
- InfiniteData,
- InvalidateOptions,
- InvalidateQueryFilters,
QueryFunction,
- QueryKey,
- RefetchOptions,
- RefetchQueryFilters,
- ResetOptions,
- ResetQueryFilters,
- SetDataOptions,
+ QueryOptions,
UseInfiniteQueryOptions,
- UseInfiniteQueryResult,
UseQueryOptions,
- UseQueryResult,
} from "react-query";
-import { QueryState } from "react-query/types/core/query";
-import { QueryFilters, Updater } from "react-query/types/core/utils";
export type QueryType = "query" | "infiniteQuery";
export type TQueryFunction = (
...args: TQueryFnArgs
) => QueryFunction;
-interface QueryToolkitBase<
+export type QueryDefaultOption<
TQueryFnData = unknown,
- TError = unknown,
TData = TQueryFnData,
-> {
- getQueryData(queryKey?: QueryKey, filters?: QueryFilters): TData | undefined;
- getQueryState(
- queryKey?: QueryKey,
- filters?: QueryFilters,
- ): QueryState | undefined;
- setQueryData(
- queryKey: QueryKey,
- updater: Updater,
- options?: SetDataOptions,
- ): TData;
- getQueriesData(filters?: QueryFilters): [QueryKey, TData][];
- setQueriesData(
- filters: QueryFilters,
- updater: Updater,
- options?: SetDataOptions,
- ): [QueryKey, TData][];
-
- invalidateQueries(
- filters?: InvalidateQueryFilters,
- options?: InvalidateOptions,
- ): Promise;
- refetchQueries(
- filters?: RefetchQueryFilters,
- options?: RefetchOptions,
- ): Promise;
- cancelQueries(filters?: QueryFilters, options?: CancelOptions): Promise;
- removeQueries(filters?: QueryFilters): void;
- resetQueries(
- filters?: ResetQueryFilters,
- options?: ResetOptions,
- ): Promise;
-
- isFetching(filters?: QueryFilters): number;
- useIsFetching(filters?: QueryFilters): number;
-}
-
-export interface QueryToolkitQueryType<
- TQueryFnArgs extends unknown[] = [],
- TQueryFnData = unknown,
TError = unknown,
- TData = TQueryFnData,
-> extends QueryToolkitBase {
- fetchInfiniteQuery: undefined;
- prefetchInfiniteQuery: undefined;
- useInfiniteQuery: undefined;
- fetchQuery(
- args: TQueryFnArgs,
- options?: Omit, "queryFn">,
- ): Promise;
- prefetchQuery(
- args: TQueryFnArgs,
- options?: Omit, "queryFn">,
- ): Promise;
- useQuery(
- args: TQueryFnArgs,
- options?: Omit, "queryFn">,
- ): UseQueryResult;
-}
+> = Omit, "queryKey" | "queryFn">;
-export interface QueryToolkitInfiniteQueryType<
- TQueryFnArgs extends unknown[] = [],
+export type UseQueryDefaultOption<
TQueryFnData = unknown,
- TError = unknown,
TData = TQueryFnData,
-> extends QueryToolkitBase {
- fetchQuery: undefined;
- prefetchQuery: undefined;
- useQuery: undefined;
- fetchInfiniteQuery(
- args: TQueryFnArgs,
- options?: Omit<
- FetchInfiniteQueryOptions,
- "queryFn"
- >,
- ): Promise>;
- prefetchInfiniteQuery(
- args: TQueryFnArgs,
- options?: Omit, "queryFn">,
- ): Promise;
- useInfiniteQuery(
- args: TQueryFnArgs,
- options?: Omit<
- UseInfiniteQueryOptions,
- "queryFn"
- >,
- ): UseInfiniteQueryResult;
-}
+ TError = unknown,
+> = Omit, "queryKey" | "queryFn">;
-export type QueryToolkit<
- TQueryFnArgs extends unknown[] = [],
+export type UseInfiniteQueryDefaultOption<
TQueryFnData = unknown,
- TError = unknown,
TData = TQueryFnData,
-> =
- | QueryToolkitQueryType
- | QueryToolkitInfiniteQueryType;
+ TError = unknown,
+> = Omit<
+ UseInfiniteQueryOptions,
+ "queryKey" | "queryFn"
+>;
diff --git a/src/types/queryToolkit.ts b/src/types/queryToolkit.ts
new file mode 100644
index 0000000..85c5beb
--- /dev/null
+++ b/src/types/queryToolkit.ts
@@ -0,0 +1,122 @@
+import {
+ CancelOptions,
+ FetchInfiniteQueryOptions,
+ FetchQueryOptions,
+ InfiniteData,
+ InvalidateOptions,
+ InvalidateQueryFilters,
+ QueryKey,
+ RefetchOptions,
+ RefetchQueryFilters,
+ ResetOptions,
+ ResetQueryFilters,
+ SetDataOptions,
+ UseInfiniteQueryOptions,
+ UseInfiniteQueryResult,
+ UseQueryOptions,
+ UseQueryResult,
+} from "react-query";
+import { QueryState } from "react-query/types/core/query";
+import { QueryFilters, Updater } from "react-query/types/core/utils";
+
+interface QueryToolkitBase<
+ TQueryFnData = unknown,
+ TError = unknown,
+ TData = TQueryFnData,
+> {
+ getQueryData(queryKey?: QueryKey, filters?: QueryFilters): TData | undefined;
+ getQueryState(
+ queryKey?: QueryKey,
+ filters?: QueryFilters,
+ ): QueryState | undefined;
+ setQueryData(
+ queryKey: QueryKey,
+ updater: Updater,
+ options?: SetDataOptions,
+ ): TData;
+ getQueriesData(filters?: QueryFilters): [QueryKey, TData][];
+ setQueriesData(
+ filters: QueryFilters,
+ updater: Updater,
+ options?: SetDataOptions,
+ ): [QueryKey, TData][];
+
+ invalidateQueries(
+ filters?: InvalidateQueryFilters,
+ options?: InvalidateOptions,
+ ): Promise;
+ refetchQueries(
+ filters?: RefetchQueryFilters,
+ options?: RefetchOptions,
+ ): Promise;
+ cancelQueries(filters?: QueryFilters, options?: CancelOptions): Promise;
+ removeQueries(filters?: QueryFilters): void;
+ resetQueries(
+ filters?: ResetQueryFilters,
+ options?: ResetOptions,
+ ): Promise;
+
+ isFetching(filters?: QueryFilters): number;
+ useIsFetching(filters?: QueryFilters): number;
+}
+
+export interface QueryToolkitQueryType<
+ TQueryFnArgs extends unknown[] = [],
+ TQueryFnData = unknown,
+ TError = unknown,
+ TData = TQueryFnData,
+> extends QueryToolkitBase {
+ fetchInfiniteQuery: undefined;
+ prefetchInfiniteQuery: undefined;
+ useInfiniteQuery: undefined;
+ fetchQuery(
+ args?: TQueryFnArgs,
+ options?: Omit, "queryFn">,
+ ): Promise;
+ prefetchQuery(
+ args?: TQueryFnArgs,
+ options?: Omit, "queryFn">,
+ ): Promise;
+ useQuery(
+ args?: TQueryFnArgs,
+ options?: Omit, "queryFn">,
+ ): UseQueryResult;
+}
+
+export interface QueryToolkitInfiniteQueryType<
+ TQueryFnArgs extends unknown[] = [],
+ TQueryFnData = unknown,
+ TError = unknown,
+ TData = TQueryFnData,
+> extends QueryToolkitBase {
+ fetchQuery: undefined;
+ prefetchQuery: undefined;
+ useQuery: undefined;
+ fetchInfiniteQuery(
+ args?: TQueryFnArgs,
+ options?: Omit<
+ FetchInfiniteQueryOptions,
+ "queryFn"
+ >,
+ ): Promise>;
+ prefetchInfiniteQuery(
+ args?: TQueryFnArgs,
+ options?: Omit, "queryFn">,
+ ): Promise;
+ useInfiniteQuery(
+ args?: TQueryFnArgs,
+ options?: Omit<
+ UseInfiniteQueryOptions,
+ "queryFn"
+ >,
+ ): UseInfiniteQueryResult;
+}
+
+export type QueryToolkit<
+ TQueryFnArgs extends unknown[] = [],
+ TQueryFnData = unknown,
+ TError = unknown,
+ TData = TQueryFnData,
+> =
+ | QueryToolkitQueryType
+ | QueryToolkitInfiniteQueryType;
diff --git a/test/createQueryToolkit/query.test.ts b/test/createQueryToolkit/query.test.ts
index dc31eeb..b0eefa3 100644
--- a/test/createQueryToolkit/query.test.ts
+++ b/test/createQueryToolkit/query.test.ts
@@ -16,7 +16,7 @@ describe("createQueryToolkit/query", () => {
it("could be used with useQuery", async () => {
const { result, waitFor } = customRenderHook(() =>
- simpleApiQuery.useQuery([], { queryKey: ["useQuery"] })
+ simpleApiQuery.useQuery([], { queryKey: ["useQuery"] }),
);
await waitFor(() => result.current.isSuccess);
@@ -28,7 +28,7 @@ describe("createQueryToolkit/query", () => {
simpleApiQuery.useQuery([], {
select: (data) => data[0].text,
queryKey: ["select"],
- })
+ }),
);
await waitFor(() => result.current.isSuccess);
@@ -65,7 +65,7 @@ describe("createQueryToolkit/query", () => {
const { result } = customRenderHook(() =>
simpleApiQuery.useQuery([], {
queryKey: ["prefetch"],
- })
+ }),
);
expect(result.current.isLoading).toEqual(false);
@@ -76,17 +76,17 @@ describe("createQueryToolkit/query", () => {
const { result } = customRenderHook(() =>
simpleApiQuery.useQuery([], {
queryKey: ["isFetching1"],
- })
+ }),
);
customRenderHook(() =>
simpleApiQuery.useQuery([], {
queryKey: ["isFetching2"],
- })
+ }),
);
const { result: isFetchingResult } = customRenderHook(() =>
- simpleApiQuery.useIsFetching()
+ simpleApiQuery.useIsFetching(),
);
expect(result.current.isFetching).toEqual(true);
@@ -102,7 +102,7 @@ describe("createQueryToolkit/query", () => {
{ text: "2", id: 2 },
{ text: "3", id: 3 },
{ text: "4", id: 4 },
- ].find((item) => item.id === id)
+ ].find((item) => item.id === id),
);
};
@@ -110,7 +110,7 @@ describe("createQueryToolkit/query", () => {
it("should pass args to api func", async () => {
const { result, waitFor } = customRenderHook(() =>
- argApiQuery.useQuery([1])
+ argApiQuery.useQuery([1]),
);
await waitFor(() => result.current.isSuccess);
@@ -136,10 +136,10 @@ describe("createQueryToolkit/query", () => {
it("should pass proper queryKey by args", async () => {
const { result: query1Res, waitFor: wait1 } = customRenderHook(() =>
- argApiQuery.useQuery([1])
+ argApiQuery.useQuery([1]),
);
const { result: query2Res, waitFor: wait2 } = customRenderHook(() =>
- argApiQuery.useQuery([2])
+ argApiQuery.useQuery([2]),
);
await wait1(() => query1Res.current.isSuccess);
@@ -152,10 +152,10 @@ describe("createQueryToolkit/query", () => {
passArgsToQueryKey: false,
});
const { result: query1Res, waitFor: wait1 } = customRenderHook(() =>
- queryNotPassArgsToQueryKey.useQuery([1])
+ queryNotPassArgsToQueryKey.useQuery([1]),
);
const { result: query2Res, waitFor: wait2 } = customRenderHook(() =>
- queryNotPassArgsToQueryKey.useQuery([2])
+ queryNotPassArgsToQueryKey.useQuery([2]),
);
await wait1(() => query1Res.current.isSuccess);
@@ -164,4 +164,58 @@ describe("createQueryToolkit/query", () => {
expect(query1Res.current.data).toEqual(query2Res.current.data);
});
});
+ describe("with default options", () => {
+ const mockData = [
+ { text: "123", id: 1 },
+ { text: "456", id: 2 },
+ ];
+ const initialData = [{ text: "initialData", id: 3 }];
+ let errorCount = 0;
+
+ const defaultOptionApi = () => () => {
+ if (errorCount++ < 2) throw new Error("error");
+ return Promise.resolve(mockData);
+ };
+
+ const defaultOptionQuery = queryToolkit(["simpleApi"], defaultOptionApi, {
+ defaultOptions: {
+ initialData,
+ enabled: false,
+ retry: 1,
+ retryDelay: 10,
+ },
+ });
+
+ it("should not fetch data", () => {
+ const { result } = customRenderHook(() => defaultOptionQuery.useQuery());
+ expect(result.current.isLoading).toEqual(false);
+ });
+
+ it("should have initial data", () => {
+ const { result } = customRenderHook(() => defaultOptionQuery.useQuery());
+ expect(result.current.data).toEqual(initialData);
+ });
+
+ it("should throw error", async () => {
+ const { result, waitFor } = customRenderHook(() =>
+ defaultOptionQuery.useQuery([], { enabled: true }),
+ );
+ expect(result.current.isFetching).toEqual(true);
+
+ await waitFor(() => result.current.isError);
+ expect(result.current.data).toEqual(initialData);
+ expect(result.current.isError).toEqual(true);
+ });
+
+ it("should get data", async () => {
+ const { result, waitFor } = customRenderHook(() =>
+ defaultOptionQuery.useQuery([]),
+ );
+ expect(result.current.isFetching).toEqual(false);
+ const data = await result.current.refetch();
+
+ await waitFor(() => !result.current.isFetching);
+ expect(data.data).toEqual(mockData);
+ });
+ });
});