Skip to content

Commit 83a78d5

Browse files
author
liaoxuan
committed
feat: support skipToken
1 parent 758bc8a commit 83a78d5

9 files changed

+125
-53
lines changed

README-zh_CN.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
<p align="center">
1515
<a href="https://github.com/liaoliao666/react-query-kit/actions/workflows/tests.yml"><img src="https://github.com/liaoliao666/react-query-kit/actions/workflows/tests.yml/badge.svg?branch=main" alt="Latest build" target="\_parent"></a>
1616
<a href="https://www.npmjs.com/package/react-query-kit"><img src="https://badgen.net/npm/v/react-query-kit" alt="Latest published version" target="\_parent"></a>
17-
<a href="https://unpkg.com/browse/react-query-kit@latest/build/zip/zip.esm.js" rel="nofollow"><img src="https://img.badgesize.io/https:/unpkg.com/react-query-kit@latest/build/zip/zip.esm.js?label=gzip%20size&compression=gzip" alt="gzip size"></a>
1817
<a href="https://github.com/liaoliao666/react-query-kit"><img src="https://badgen.net/npm/types/react-query-kit" alt="Types included" target="\_parent"></a>
1918
<a href="https://www.npmjs.com/package/react-query-kit"><img src="https://badgen.net/npm/license/react-query-kit" alt="License" target="\_parent"></a>
2019
<a href="https://www.npmjs.com/package/react-query-kit"><img src="https://badgen.net/npm/dt/react-query-kit" alt="Number of downloads" target="\_parent"></a>
@@ -28,7 +27,7 @@
2827

2928
- 以类型安全的方式管理 `queryKey`
3029
-`queryClient` 的操作更清楚地关联到哪个自定义 hook
31-
- 可以从任何自定义 ReactQuery 挂钩中提取的 TypeScript 类型
30+
- 可以从任何自定义 ReactQuery hook 中提取的 TypeScript 类型
3231
- 中间件
3332

3433
[English](./README.md) | 简体中文
@@ -50,6 +49,7 @@
5049
- [中间件](#中间件)
5150
- [TypeScript](#typescript)
5251
- [类型推导](#类型推导)
52+
- [禁用查询](#禁用查询)
5353
- [常见问题](#常见问题)
5454
- [迁移](#迁移)
5555
- [Issues](#issues)
@@ -649,6 +649,24 @@ inferError<typeof useProjects> // Error
649649
inferOptions<typeof useProjects> // InfiniteQueryHookOptions<...>
650650
```
651651

652+
## 禁用查询
653+
654+
要禁用查询,您可以将 `skipToken` 作为选项 `variables` 传递给您的自定义查询。这将阻止查询被执行。
655+
656+
```ts
657+
import { skipToken } from '@tanstack/react-query'
658+
659+
const [name, setName] = useState<string | undefined>()
660+
const result = usePost({
661+
variables: id ? { id: id } : skipToken,
662+
})
663+
664+
// 以及用于 useQueries 的示例
665+
const queries = useQueries({
666+
queries: [usePost.getOptions(id ? { id: id } : skipToken)],
667+
})
668+
```
669+
652670
## 常见问题
653671

654672
### `getFetchOptions``getOptions` 有什么不同

README.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
<p align="center">
1515
<a href="https://github.com/liaoliao666/react-query-kit/actions/workflows/tests.yml"><img src="https://github.com/liaoliao666/react-query-kit/actions/workflows/tests.yml/badge.svg?branch=main" alt="Latest build" target="\_parent"></a>
1616
<a href="https://www.npmjs.com/package/react-query-kit"><img src="https://badgen.net/npm/v/react-query-kit" alt="Latest published version" target="\_parent"></a>
17-
<a href="https://unpkg.com/browse/react-query-kit@latest/build/zip/zip.esm.js" rel="nofollow"><img src="https://img.badgesize.io/https:/unpkg.com/react-query-kit@latest/build/zip/zip.esm.js?label=gzip%20size&compression=gzip" alt="gzip size"></a>
1817
<a href="https://github.com/liaoliao666/react-query-kit"><img src="https://badgen.net/npm/types/react-query-kit" alt="Types included" target="\_parent"></a>
1918
<a href="https://github.com/liaoliao666/react-query-kit/blob/main/LICENSE"><img src="https://badgen.net/npm/license/react-query-kit" alt="License" target="\_parent"></a>
2019
<a href="https://www.npmjs.com/package/react-query-kit"><img src="https://badgen.net/npm/dt/react-query-kit" alt="Number of downloads" target="\_parent"></a>
@@ -50,6 +49,7 @@ English | [简体中文](./README-zh_CN.md)
5049
- [Middleware](#middleware)
5150
- [TypeScript](#typescript)
5251
- [Type inference](#type-inference)
52+
- [Disabling Queries](#disabling-queries)
5353
- [FAQ](#faq)
5454
- [Migration](#migration)
5555
- [Issues](#issues)
@@ -649,6 +649,24 @@ inferError<typeof useProjects> // Error
649649
inferOptions<typeof useProjects> // InfiniteQueryHookOptions<...>
650650
```
651651

652+
## Disabling Queries
653+
654+
To disable queries, you can pass `skipToken` as the option `variables` to your custom query. This will prevent the query from being executed.
655+
656+
```ts
657+
import { skipToken } from '@tanstack/react-query'
658+
659+
const [name, setName] = useState<string | undefined>()
660+
const result = usePost({
661+
variables: id ? { id: id } : skipToken,
662+
})
663+
664+
// and for useQueries example
665+
const queries = useQueries({
666+
queries: [usePost.getOptions(id ? { id: id } : skipToken)],
667+
})
668+
```
669+
652670
## FAQ
653671

654672
### What is the difference between `getFetchOptions` and `getOptions`?

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"@rollup/plugin-commonjs": "^22.0.2",
2828
"@rollup/plugin-node-resolve": "^13.2.1",
2929
"@rollup/plugin-replace": "^4.0.0",
30-
"@tanstack/react-query": "^5.28.6",
30+
"@tanstack/react-query": "^5.35.1",
3131
"@testing-library/jest-dom": "^5.16.5",
3232
"@testing-library/react": "^14.0.0",
3333
"@trivago/prettier-plugin-sort-imports": "^4.2.0",

rollup.config.js

-24
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export default function rollup() {
3535
cjs(options),
3636
umdDev(options),
3737
umdProd(options),
38-
esmZip(options),
3938
]
4039
}
4140

@@ -121,29 +120,6 @@ function umdProd({ input, external, globals, jsName }) {
121120
name: jsName,
122121
globals,
123122
},
124-
plugins: [
125-
babelPlugin,
126-
commonJS(),
127-
nodeResolve({ extensions }),
128-
replaceDevPlugin('production'),
129-
terser({
130-
mangle: true,
131-
compress: true,
132-
}),
133-
],
134-
}
135-
}
136-
137-
function esmZip({ input, external, globals, jsName }) {
138-
return {
139-
external,
140-
input,
141-
output: {
142-
format: 'esm',
143-
file: `build/zip/zip.esm.js`,
144-
name: jsName,
145-
globals,
146-
},
147123
plugins: [
148124
babelPlugin,
149125
commonJS(),

src/createBaseQuery.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type {
2-
QueryClient,
3-
QueryFunctionContext,
4-
UseBaseQueryOptions,
5-
UseInfiniteQueryOptions,
1+
import {
2+
type QueryClient,
3+
type QueryFunctionContext,
4+
type UseBaseQueryOptions,
5+
type UseInfiniteQueryOptions,
66
} from '@tanstack/react-query'
77

8-
import { getKey as getFullKey, withMiddleware } from './utils'
8+
import { ReactQuery, getKey as getFullKey, withMiddleware } from './utils'
99

1010
type QueryBaseHookOptions = Omit<
1111
UseBaseQueryOptions,
@@ -38,7 +38,10 @@ export const createBaseQuery = (
3838

3939
const getQueryOptions = (fetcherFn: any, variables: any) => {
4040
return {
41-
queryFn: (context: QueryFunctionContext) => fetcherFn(variables, context),
41+
queryFn:
42+
variables && variables === ReactQuery.skipToken
43+
? ReactQuery.skipToken
44+
: (context: QueryFunctionContext) => fetcherFn(variables, context),
4245
queryKey: getFullKey(defaultOptions.queryKey, variables),
4346
}
4447
}

src/types.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
QueryKey,
1414
QueryKeyHashFunction,
1515
QueryObserverSuccessResult,
16+
SkipToken,
1617
UseInfiniteQueryOptions,
1718
UseInfiniteQueryResult,
1819
UseMutationOptions,
@@ -100,7 +101,9 @@ export type ExposeMethods<TFnData, TVariables, TError, TPageParam = never> = {
100101
QueryKey
101102
>
102103
getFetchOptions: (
103-
variables: TVariables extends void ? TVariables | void : TVariables
104+
variables: TVariables extends void
105+
? CompatibleWithV4<TVariables | SkipToken, TVariables> | void
106+
: CompatibleWithV4<TVariables | SkipToken, TVariables>
104107
) => Pick<
105108
ReturnType<
106109
ExposeMethods<TFnData, TVariables, TError, TPageParam>['getOptions']
@@ -117,7 +120,9 @@ export type ExposeMethods<TFnData, TVariables, TError, TPageParam = never> = {
117120
| 'initialPageParam'
118121
>
119122
getOptions: (
120-
variables: TVariables extends void ? TVariables | void : TVariables
123+
variables: TVariables extends void
124+
? CompatibleWithV4<TVariables | SkipToken, TVariables> | void
125+
: CompatibleWithV4<TVariables | SkipToken, TVariables>
121126
) => [TPageParam] extends [never]
122127
? CompatibleWithV4<
123128
UseQueryOptions<TFnData, TError, TFnData, QueryKey> & {
@@ -169,7 +174,7 @@ export interface QueryHookOptions<TFnData, TError, TData, TVariables>
169174
'queryKey' | 'queryFn' | 'queryKeyHashFn'
170175
> {
171176
use?: Middleware<QueryHook<TFnData, TVariables, TError>>[]
172-
variables?: TVariables
177+
variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>
173178
}
174179

175180
export interface DefinedQueryHookOptions<TFnData, TError, TData, TVariables>
@@ -242,7 +247,7 @@ export interface SuspenseQueryHookOptions<TFnData, TError, TData, TVariables>
242247
| 'useErrorBoundary'
243248
> {
244249
use?: Middleware<SuspenseQueryHook<TFnData, TVariables, TVariables>>[]
245-
variables?: TVariables
250+
variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>
246251
}
247252

248253
export type SuspenseQueryHookResult<TData, TError> = Omit<
@@ -301,7 +306,7 @@ export interface InfiniteQueryHookOptions<
301306
| 'getNextPageParam'
302307
> {
303308
use?: Middleware<InfiniteQueryHook<TFnData, TVariables, TError, TPageParam>>[]
304-
variables?: TVariables
309+
variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>
305310
}
306311

307312
export interface DefinedInfiniteQueryHookOptions<
@@ -411,7 +416,7 @@ export interface SuspenseInfiniteQueryHookOptions<
411416
| 'useErrorBoundary'
412417
> {
413418
use?: Middleware<SuspenseInfiniteQueryHook<TFnData, TVariables, TVariables>>[]
414-
variables?: TVariables
419+
variables?: CompatibleWithV4<TVariables | SkipToken, TVariables>
415420
}
416421

417422
export type SuspenseInfiniteQueryHookResult<TData, TError> = Omit<

tests/createQuery.test.tsx

+49-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { QueryClient } from '@tanstack/react-query'
1+
import { QueryClient, skipToken } from '@tanstack/react-query'
22
import '@testing-library/jest-dom'
3-
import { waitFor } from '@testing-library/react'
3+
import { fireEvent, waitFor } from '@testing-library/react'
44
import * as React from 'react'
55

66
import { createQuery } from '../src'
77
import type { QueryHookResult } from '../src'
88
import { Middleware } from '../src/types'
9-
import { omit, renderWithClient, uniqueKey } from './utils'
9+
import { omit, renderWithClient, sleep, uniqueKey } from './utils'
1010

1111
describe('createQuery', () => {
1212
const queryClient = new QueryClient()
@@ -138,4 +138,50 @@ describe('createQuery', () => {
138138

139139
await waitFor(() => rendered.getByText('selectedData'))
140140
})
141+
142+
it('should respect skipToken and refetch when skipToken is taken away', async () => {
143+
const useGeneratedQuery = createQuery<string>({
144+
queryKey: uniqueKey(),
145+
fetcher: async () => {
146+
await sleep(10)
147+
return Promise.resolve('data')
148+
},
149+
})
150+
151+
function Page({ enabled }: { enabled: boolean }) {
152+
const { data, status } = useGeneratedQuery({
153+
variables: enabled ? undefined : skipToken,
154+
retry: false,
155+
retryOnMount: false,
156+
refetchOnMount: false,
157+
refetchOnWindowFocus: false,
158+
})
159+
160+
return (
161+
<div>
162+
<div>status: {status}</div>
163+
<div>data: {String(data)}</div>
164+
</div>
165+
)
166+
}
167+
168+
function App() {
169+
const [enabled, toggle] = React.useReducer(x => !x, false)
170+
171+
return (
172+
<div>
173+
<Page enabled={enabled} />
174+
<button onClick={toggle}>enable</button>
175+
</div>
176+
)
177+
}
178+
179+
const rendered = renderWithClient(queryClient, <App />)
180+
181+
await waitFor(() => rendered.getByText('status: pending'))
182+
183+
fireEvent.click(rendered.getByRole('button', { name: 'enable' }))
184+
await waitFor(() => rendered.getByText('status: success'))
185+
await waitFor(() => rendered.getByText('data: data'))
186+
})
141187
})

tests/utils.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,9 @@ export function omit<T extends object, K extends string[]>(
3232
Object.entries(object || {}).filter(([key]) => !paths.includes(key))
3333
) as Pick<T, Exclude<keyof T, K[number]>>
3434
}
35+
36+
export function sleep(timeout: number): Promise<void> {
37+
return new Promise((resolve, _reject) => {
38+
setTimeout(resolve, timeout)
39+
})
40+
}

yarn.lock

+9-9
Original file line numberDiff line numberDiff line change
@@ -1676,17 +1676,17 @@
16761676
dependencies:
16771677
"@sinonjs/commons" "^3.0.0"
16781678

1679-
"@tanstack/query-core@5.28.6":
1680-
version "5.28.6"
1681-
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.28.6.tgz#a3bdb108f9f8d4e2ba3163068dbe6ff55b905a81"
1682-
integrity sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==
1679+
"@tanstack/query-core@5.35.1":
1680+
version "5.35.1"
1681+
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.35.1.tgz#a7e6cbf0f252475da19ba9cba6567e8fe683b2ee"
1682+
integrity sha512-0Dnpybqb8+ps6WgqBnqFEC+1F/xLvUosRAq+wiGisTgolOZzqZfkE2995dEXmhuzINiTM7/a6xSGznU0NIvBkw==
16831683

1684-
"@tanstack/react-query@^5.28.6":
1685-
version "5.28.6"
1686-
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.28.6.tgz#0d52b0a98a1d842debf9c65496e20a9981a23bc4"
1687-
integrity sha512-/DdYuDBSsA21Qbcder1R8Cr/3Nx0ZnA2lgtqKsLMvov8wL4+g0HBz/gWYZPlIsof7iyfQafyhg4wUVUsS3vWZw==
1684+
"@tanstack/react-query@^5.35.1":
1685+
version "5.35.1"
1686+
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.35.1.tgz#3b7c710bb32c6c71e0cbe64029dded9b0cbd9a0f"
1687+
integrity sha512-i2T7m2ffQdNqlX3pO+uMsnQ0H4a59Ens2GxtlMsRiOvdSB4SfYmHb27MnvFV8rGmtWRaa4gPli0/rpDoSS5LbQ==
16881688
dependencies:
1689-
"@tanstack/query-core" "5.28.6"
1689+
"@tanstack/query-core" "5.35.1"
16901690

16911691
"@testing-library/dom@^9.0.0":
16921692
version "9.3.0"

0 commit comments

Comments
 (0)