Skip to content

Commit 62defc2

Browse files
committed
feat: support middleware & new expose method getFetchOptions
1 parent 34949b0 commit 62defc2

21 files changed

Lines changed: 707 additions & 649 deletions

.eslintrc

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"prefer-const": "error",
3737
"curly": ["warn", "multi-line", "consistent"],
3838
"no-console": "off",
39+
"@typescript-eslint/no-non-null-assertion": "off",
3940
"import/no-unresolved": ["error", { "commonjs": true, "amd": true }],
4041
"import/export": "error",
4142
"@typescript-eslint/no-duplicate-imports": ["error"],
@@ -52,30 +53,7 @@
5253
"error",
5354
{ "fn": "it", "withinDescribe": "it" }
5455
],
55-
"import/order": [
56-
"error",
57-
{
58-
"alphabetize": { "order": "asc", "caseInsensitive": true },
59-
"groups": [
60-
"builtin",
61-
"external",
62-
"internal",
63-
"parent",
64-
"sibling",
65-
"index",
66-
"object"
67-
],
68-
"newlines-between": "never",
69-
"pathGroups": [
70-
{
71-
"pattern": "react",
72-
"group": "builtin",
73-
"position": "before"
74-
}
75-
],
76-
"pathGroupsExcludedImportTypes": ["builtin"]
77-
}
78-
],
56+
"import/order": "off",
7957
"react/jsx-uses-react": "off",
8058
"react/react-in-jsx-scope": "off",
8159
"sort-imports": [

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v16.19.0

README-zh_CN.md

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
- [createSuspenseQuery](#createsuspensequery)
4343
- [createSuspenseInfiniteQuery](#createsuspenseinfinitequery)
4444
- [createMutation](#createmutation)
45+
- [中间件](#中间件)
4546
- [类型推导](#类型推导)
46-
- [注意事项](#注意事项)
4747
- [问题](#issues)
4848
- [🐛 Bugs](#-bugs)
4949
- [💡 Feature Requests](#-feature-requests)
@@ -86,13 +86,6 @@ const usePost = createQuery<Response, Variables, Error>({
8686
// 如果你只想在有id时且没有数据时请求,可以这么设置
8787
enabled: (data, variables) => !data && variables.id,
8888
suspense: true,
89-
// 你也可以通过 useDefaultOptions 传入默认选项
90-
useDefaultOptions: () => {
91-
const { id } = useSomething()
92-
return {
93-
variables: { id }
94-
}
95-
}
9689
})
9790

9891
const variables = { id: 1 }
@@ -117,7 +110,7 @@ console.log(usePost.getKey(variables)) // ['/posts', { id: 1 }]
117110
export async function getStaticProps() {
118111
const queryClient = new QueryClient()
119112

120-
await queryClient.prefetchQuery(usePost.getKey(variables), usePost.queryFn)
113+
await queryClient.prefetchQuery(usePost.getFetchOptions(variables))
121114

122115
return {
123116
props: {
@@ -128,15 +121,14 @@ export async function getStaticProps() {
128121

129122
// 在 react 组件外使用
130123
const data = await queryClient.fetchQuery(
131-
usePost.getKey(variables),
132-
usePost.queryFn
124+
usePost.getFetchOptions(variables)
133125
)
134126

135127
// useQueries 例子
136128
const queries = useQueries({
137129
queries: [
138-
{ queryKey: usePost.getKey(variables), queryFn: usePost.queryFn },
139-
{ queryKey: useProjects.getKey(), queryFn: useProjects.queryFn },
130+
usePost.getFetchOptions(variables)
131+
useProjects.getFetchOptions(),
140132
],
141133
})
142134

@@ -155,14 +147,15 @@ Options
155147
- 可选
156148
- 将此设置为 `false` 以禁用此查询自动运行。
157149
- 如果设置为函数,该函数将使用最新数据执行以计算布尔值
158-
- `useDefaultOptions: () => QueryHookOptions`
150+
- `use: Middleware[]`
159151
- 可选
160-
- 如果你想将其他钩子的返回值注入到当前 query 中,你可以使用这个选项。
152+
- 中间件函数数组 [(详情)](#中间件)
161153

162154
Expose Methods
163155

164156
- `getPrimaryKey: () => primaryKey`
165157
- `getKey: (variables: TVariables) => [primaryKey, variables]`
158+
- `getFetchOptions: (variables: TVariables) => {queryKey, queryFn, queryKeyHashFn}`
166159
- `queryFn: QueryFunction<TFnData, [primaryKey, TVariables]>`
167160
- `queryKeyHashFn: (queryKey: [primaryKey, TVariables]) => string`
168161

@@ -236,8 +229,7 @@ export async function getStaticProps() {
236229
const queryClient = new QueryClient()
237230

238231
await queryClient.prefetchInfiniteQuery(
239-
useProjects.getKey(variables),
240-
useProjects.queryFn
232+
useProjects.getFetchOptions(variables)
241233
)
242234

243235
return {
@@ -249,8 +241,7 @@ export async function getStaticProps() {
249241

250242
// 在 react 组件外使用
251243
const data = await queryClient.fetchInfiniteQuery(
252-
useProjects.getKey(variables),
253-
useProjects.queryFn
244+
useProjects.getFetchOptions(variables)
254245
)
255246
```
256247

@@ -265,14 +256,15 @@ Options
265256
- 可选
266257
- 将此设置为 `false` 以禁用此查询自动运行。
267258
- 如果设置为函数,该函数将使用最新数据执行以计算布尔值
268-
- `useDefaultOptions: () => InfiniteQueryHookOptions`
259+
- `use: Middleware[]`
269260
- 可选
270-
- 如果你想将其他钩子的返回值注入到当前 query 中,你可以使用这个选项。
261+
- 中间件函数数组 [(详情)](#中间件)
271262

272263
Expose Methods
273264

274265
- `getPrimaryKey: () => primaryKey`
275266
- `getKey: (variables: TVariables) => [primaryKey, variables]`
267+
- `getFetchOptions: (variables: TVariables) => {queryKey, queryFn, queryKeyHashFn}`
276268
- `queryFn: QueryFunction<TFnData, [primaryKey, TVariables]>`
277269
- `queryKeyHashFn: (queryKey: [primaryKey, TVariables]) => string`
278270

@@ -411,47 +403,87 @@ useAddTodo.mutationFn({ title: 'Do Laundry', content: 'content...' })
411403

412404
Options
413405

414-
- `useDefaultOptions: () => MutationHookOptions`
406+
- `use: Middleware[]`
415407
- 可选
416-
- 如果你想将其他钩子的返回值注入到当前 mutation 中,你可以使用这个选项。
408+
- 中间件函数数组 [(详情)](#中间件)
417409

418410
Returns
419411

420412
- `getKey: () => MutationKey`
421413
- `mutationFn: MutationFunction<TData, TVariables>`
422414

423-
## 类型推导
415+
## 中间件
424416

425-
您可以使用 `inferVariables``inferData` 提取任何自定义 hook 的 TypeScript 类型
417+
此功能的灵感来自于 [SWR 的中间件功能](https://swr.vercel.app/docs/middleware)
418+
419+
中间件接收 hook,可以在运行它之前和之后执行逻辑。如果有多个中间件,则每个中间件包装下一个中间件。列表中的最后一个中间件将接收原始的 hook。
420+
421+
### 使用
426422

427423
```ts
428-
import { inferVariables, inferData, inferFnData } from 'react-query-kit'
424+
import { Middleware, MutationHook, QueryHook } from 'react-query-kit'
425+
426+
const myMiddleware: Middleware<
427+
QueryHook<Response, Variables>
428+
> = useQueryNext => {
429+
return options => {
430+
const { userId } = useAuth()
431+
return useQueryNext({
432+
...options,
433+
variables: options.variables ?? { id: userId },
434+
})
435+
}
436+
}
429437

430-
type Variables = inferVariables<typeof usePost>
431-
type Data = inferData<typeof usePost>
432-
type FnData = inferFnData<typeof usePost>
438+
const useUser = createQuery<Response, Variables>({
439+
// ...
440+
use: [myMiddleware],
441+
})
442+
443+
// 全局中间件
444+
const queryMiddleware = Middleware<QueryHook>
445+
const mutationMiddleware = Middleware<MutationHook>
446+
447+
const queryClient = createQueryClient({
448+
queries: {
449+
use: [queryMiddleware],
450+
},
451+
mutations: {
452+
use: [mutationMiddleware],
453+
},
454+
})
433455
```
434456

435-
## 注意事项
457+
### 多个中间件
436458

437-
由于 `createQuery``createInfiniteQuery``varibables` 类型默认为 `any`,当你没有设置 `varibables` 的类型时,自定义钩子的 `varibables` 选项可以传递任何值,如下所示
459+
每个中间件包装下一个中间件,最后一个只包装 useQuery hook。例如:
438460

439-
```ts
440-
const usePost = createQuery<Response>({...})
441-
usePost({
442-
// 这将不会抛出类型错误
443-
variables: {foo: 1}
444-
})
461+
```jsx
462+
createQuery({ use: [a, b, c] })
445463
```
446464

447-
为了进行更严格的类型验证,当你不想传递`variables`选项时,我建议你使用`void`类型作为`variables`类型,如下图。当你向变量传递值时,usePost 会抛出一个 TypeError。
465+
中间件执行的顺序是 `a → b → c`,如下所示:
466+
467+
```plaintext
468+
enter a
469+
enter b
470+
enter c
471+
useQuery()
472+
exit c
473+
exit b
474+
exit a
475+
```
476+
477+
## 类型推导
478+
479+
您可以使用 `inferVariables``inferData` 提取任何自定义 hook 的 TypeScript 类型
448480

449481
```ts
450-
const usePost = createQuery<Response, void>({...})
451-
usePost({
452-
// 这将抛出一个类型错误
453-
variables: {foo: 1}
454-
})
482+
import { inferData, inferFnData, inferVariables } from 'react-query-kit'
483+
484+
type Variables = inferVariables<typeof usePost>
485+
type Data = inferData<typeof usePost>
486+
type FnData = inferFnData<typeof usePost>
455487
```
456488
457489
## Issues

0 commit comments

Comments
 (0)