From 7bd7e17900c2725d4144a0b3c05c756d2eb85a47 Mon Sep 17 00:00:00 2001 From: liaoxuan Date: Thu, 7 Dec 2023 15:12:49 +0800 Subject: [PATCH] feat: optimize code & doc --- README-zh_CN.md | 54 ++++++++++++---------------------- README.md | 60 +++++++++++++------------------------- src/types.ts | 12 ++++---- src/utils.ts | 10 ++----- tests/createQuery.test.tsx | 12 +++++++- 5 files changed, 59 insertions(+), 89 deletions(-) diff --git a/README-zh_CN.md b/README-zh_CN.md index 7ee4743..faed077 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -61,9 +61,9 @@ ## Installation ```bash -$ npm i react-query-kit@beta +$ npm i react-query-kit # or -$ yarn add react-query-kit@beta +$ yarn add react-query-kit ``` 如果您还在使用 React Query Kit v2? 请在此处查看 v2 文档:https://github.com/liaoliao666/react-query-kit/tree/v2#readme. @@ -382,7 +382,7 @@ Returns ```tsx import { router } from 'react-query-kit' -const posts = router(`posts`, { +const post = router(`post`, { byId: router.query({ fetcher: (variables: { id: number }) => fetch(`/posts/${variables.id}`).then(res => res.json()), @@ -406,28 +406,29 @@ const posts = router(`posts`, { }) // get root key -posts.getKey() // ['posts'] +post.getKey() // ['post'] // hooks -posts.byId.useQuery({ variables: { id: 1 } }) -posts.byId.useSuspenseQuery({ variables: { id: 1 } }) -posts.list.useInfiniteQuery() -posts.list.useSuspenseInfiniteQuery() -posts.add.useMutation() +post.byId.useQuery({ variables: { id: 1 } }) +post.byId.useSuspenseQuery({ variables: { id: 1 } }) +post.list.useInfiniteQuery() +post.list.useSuspenseInfiniteQuery() +post.add.useMutation() // expose methods -posts.byId.getKey({ id: 1 }) // ['posts', 'byId', { id: 1 }] -posts.byId.getFetchOptions({ id: 1 }) -posts.byId.getOptions({ id: 1 }) -posts.byId.fetcher({ id: 1 }) -posts.add.getKey() // ['posts', 'add'] -posts.add.getOptions() -posts.add.mutationFn({ title: 'title', content: 'content' }) +post.byId.getKey({ id: 1 }) // ['post', 'byId', { id: 1 }] +post.byId.getFetchOptions({ id: 1 }) +post.byId.getOptions({ id: 1 }) +post.byId.fetcher({ id: 1 }) +post.add.getKey() // ['post', 'add'] +post.add.getOptions() +post.add.mutationFn({ title: 'title', content: 'content' }) // infer types type Data = inferData type FnData = inferFnData type Variables = inferVariables +type Error = inferError ``` ## API 文档 @@ -592,26 +593,6 @@ inferOptions // InfiniteQueryHookOptions<...> `getFetchOptions` 只会返回必要的选项,而像 `staleTime` 和 `retry` 等选项会被忽略 -```ts -const useTest1 = createQuery({ - staleTime: Infinity, -}) - -// 只有在第一次请求 -queryClient.prefetchQuery(useTest1.getOptions()) -// 永远会去请求 -queryClient.prefetchQuery(useTest1.getFetchOptions()) - -const useTest2 = createQuery({ - retry: 3, -}) - -// 会自动重试3次 -queryClient.prefetchQuery(useTest2.getOptions()) -// 不会自动重试 -queryClient.prefetchQuery(useTest2.getFetchOptions()) -``` - ### `fetcher` 和 `queryFn` 有什么不同 ReactQueryKit 会自动将 `fetcher` 转换为 `queryFn`,例如 @@ -648,6 +629,7 @@ createQuery({ - 支持传入数组 `queryKey` - 支持推断 fetcher 的类型,您可以自动享受首选的类型。 +- 支持创建整个 API 的形状 ## Issues diff --git a/README.md b/README.md index 4cf2ba4..3e1a744 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,9 @@ This module is distributed via [npm][npm] which is bundled with [node][node] and should be installed as one of your project's `dependencies`: ```bash -$ npm i react-query-kit@beta +$ npm i react-query-ki # or -$ yarn add react-query-kit@beta +$ yarn add react-query-kit ``` If you still on React Query Kit v2? Check out the v2 docs here: https://github.com/liaoliao666/react-query-kit/tree/v2#readme. @@ -347,7 +347,7 @@ function App() { mutation.mutate({ title: 'Do Laundry', content: 'content...' }) }} > - Create Todo + create Todo )} @@ -382,7 +382,7 @@ Returns ```tsx import { router } from 'react-query-kit' -const posts = router(`posts`, { +const post = router(`post`, { byId: router.query({ fetcher: (variables: { id: number }) => fetch(`/posts/${variables.id}`).then(res => res.json()), @@ -406,28 +406,29 @@ const posts = router(`posts`, { }) // get root key -posts.getKey() // ['posts'] +post.getKey() // ['post'] // hooks -posts.byId.useQuery({ variables: { id: 1 } }) -posts.byId.useSuspenseQuery({ variables: { id: 1 } }) -posts.list.useInfiniteQuery() -posts.list.useSuspenseInfiniteQuery() -posts.add.useMutation() +post.byId.useQuery({ variables: { id: 1 } }) +post.byId.useSuspenseQuery({ variables: { id: 1 } }) +post.list.useInfiniteQuery() +post.list.useSuspenseInfiniteQuery() +post.add.useMutation() // expose methods -posts.byId.getKey({ id: 1 }) // ['posts', 'byId', { id: 1 }] -posts.byId.getFetchOptions({ id: 1 }) -posts.byId.getOptions({ id: 1 }) -posts.byId.fetcher({ id: 1 }) -posts.add.getKey() // ['posts', 'add'] -posts.add.getOptions() -posts.add.mutationFn({ title: 'title', content: 'content' }) +post.byId.getKey({ id: 1 }) // ['post', 'byId', { id: 1 }] +post.byId.getFetchOptions({ id: 1 }) +post.byId.getOptions({ id: 1 }) +post.byId.fetcher({ id: 1 }) +post.add.getKey() // ['post', 'add'] +post.add.getOptions() +post.add.mutationFn({ title: 'title', content: 'content' }) // infer types type Data = inferData type FnData = inferFnData type Variables = inferVariables +type Error = inferError ``` ## API Reference @@ -590,31 +591,11 @@ inferOptions // InfiniteQueryHookOptions<...> ### What is the difference between `getFetchOptions` and `getOptions`? -`getFetchOptions` will only return necessary options, while options like `staleTime` and `retry` will be omited - -```ts -const useTest1 = createQuery({ - staleTime: Infinity, -}) - -// Only triggers on the first request -queryClient.prefetchQuery(useTest1.getOptions()) -// Will always trigger a request -queryClient.prefetchQuery(useTest1.getFetchOptions()) - -const useTest2 = createQuery({ - retry: 3, -}) - -// Automatically retries 3 times -queryClient.prefetchQuery(useTest2.getOptions()) -// Does not automatically retry -queryClient.prefetchQuery(useTest2.getFetchOptions()) -``` +`getFetchOptions` would only return necessary options, while options like `staleTime` and `retry` would be omited ### What is the difference between `fetcher` and `queryFn`? -ReactQueryKit automatically converts fetcher to queryFn, as shown below: +ReactQueryKit would automatically converts fetcher to queryFn, as shown below: ```ts const useTest = createQuery({ @@ -648,6 +629,7 @@ What you benefit from ReactQueryKit 3 - Support hierarchical key - Support infer the types of fetcher, you can enjoy the preferred types automatically. +- Support to create a shape of your entire API ## Issues diff --git a/src/types.ts b/src/types.ts index 5e307a8..9992a66 100644 --- a/src/types.ts +++ b/src/types.ts @@ -517,9 +517,9 @@ export type inferFnData = T extends { ? TFnData : never -export type inferError = T extends { - fetcher: ExposeFetcher -} +export type inferError = T extends ExposeMethods + ? TError + : T extends ExposeMethods ? TError : T extends ExposeMutationMethods ? TError @@ -668,19 +668,19 @@ export type CreateRouter = { TFnData, DefaultTo, DefaultTo, - TPageParam + DefaultTo > useSuspenseInfiniteQuery: SuspenseInfiniteQueryHook< TFnData, DefaultTo, DefaultTo, - TPageParam + DefaultTo > } & ExposeMethods< TFnData, DefaultTo, DefaultTo, - TPageParam + DefaultTo > : TConfig[K] extends Omit< RouterQuery, diff --git a/src/utils.ts b/src/utils.ts index 65bdb34..8a9f4e6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -23,7 +23,7 @@ export const withMiddleware = ( options?: { client?: QueryClient; use?: Middleware[] }, queryClient?: QueryClient ) { - const [middleware, opts] = [ + const [uses, opts]: [Middleware[], any] = [ ReactQuery.useQueryClient( // @ts-ignore Compatible with ReactQuery v4 isV5 ? queryClient : options @@ -37,13 +37,9 @@ export const withMiddleware = ( ], [[]] ) + const composed = uses.reduceRight((next, use) => use(next), hook) - let next = hook - for (let i = middleware.length; i--; ) { - next = middleware[i](next) - } - - return next(opts, queryClient) + return composed(opts, queryClient) } } diff --git a/tests/createQuery.test.tsx b/tests/createQuery.test.tsx index 51b4cfd..84022df 100644 --- a/tests/createQuery.test.tsx +++ b/tests/createQuery.test.tsx @@ -53,7 +53,17 @@ describe('createQuery', () => { fetcher: (_variables: { id: number }) => { return 'test' }, - use: [myMiddileware], + use: [ + useNext => { + return options => + useNext({ + ...options, + initialData: 'fakeData', + enabled: false, + }) + }, + myMiddileware, + ], }) const states: QueryHookResult[] = []