@qiaopeng/tanstack-query-plus 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/hooks/usePrefetch.d.ts +1 -0
- package/dist/hooks/usePrefetch.d.ts.map +1 -1
- package/dist/hooks/usePrefetch.js +22 -5
- package/dist/react-query/index.d.ts +2 -2
- package/dist/react-query/index.d.ts.map +1 -1
- package/dist/react-query/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -210,7 +210,7 @@ function Dashboard() {
|
|
|
210
210
|
|
|
211
211
|
## 8. 预取(Prefetch)
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
提供多种预取策略:悬停、路由变化、智能预取、视口内预取(可选依赖),并支持 `minInterval` 节流与 `stale` 检查。
|
|
214
214
|
|
|
215
215
|
```tsx
|
|
216
216
|
import { useEffect } from 'react'
|
|
@@ -218,21 +218,21 @@ import { useHoverPrefetch, useRoutePrefetch, useSmartPrefetch } from '@qiaopeng/
|
|
|
218
218
|
import { queryKeys } from '@qiaopeng/tanstack-query-plus/core'
|
|
219
219
|
|
|
220
220
|
function LinkWithPrefetch({ id }: { id: string }) {
|
|
221
|
-
const hover = useHoverPrefetch(queryKeys.user(id), () => fetch(`/api/users/${id}`).then(r => r.json()))
|
|
221
|
+
const hover = useHoverPrefetch(queryKeys.user(id), () => fetch(`/api/users/${id}`).then(r => r.json()), { hoverDelay: 200, minInterval: 1000 })
|
|
222
222
|
return <a href={`/user/${id}`} {...hover}>用户详情</a>
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
function RouterChange() {
|
|
226
226
|
const prefetch = useRoutePrefetch()
|
|
227
227
|
useEffect(() => {
|
|
228
|
-
prefetch(queryKeys.settings(), () => fetch('/api/settings').then(r => r.json()))
|
|
228
|
+
prefetch(queryKeys.settings(), () => fetch('/api/settings').then(r => r.json()), { minInterval: 1000 })
|
|
229
229
|
}, [])
|
|
230
230
|
return null
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
function SmartCard({ id }: { id: string }) {
|
|
234
234
|
const { prefetch } = useSmartPrefetch()
|
|
235
|
-
return <div onMouseEnter={() => prefetch(queryKeys.user(id), () => fetch(`/api/users/${id}`).then(r => r.json()))}>卡片</div>
|
|
235
|
+
return <div onMouseEnter={() => prefetch(queryKeys.user(id), () => fetch(`/api/users/${id}`).then(r => r.json()), { minInterval: 1000 })}>卡片</div>
|
|
236
236
|
}
|
|
237
237
|
```
|
|
238
238
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrefetch.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrefetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMrE,MAAM,WAAW,eAAe;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"usePrefetch.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrefetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMrE,MAAM,WAAW,eAAe;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;AAChH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAAG,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE;AACrF,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAAG,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;AASjI,wBAAgB,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,GAAE,oBAAyB;;;;EAwBtI;AAGD,wBAAgB,gBAAgB,KAGV,KAAK,sBAAsB,QAAQ,WAAW,aAAa,CAAC,KAAK,CAAC,YAAY,eAAe,UAUlH;AAED,wBAAgB,gBAAgB,KAEV,KAAK,qBAAqB,KAAK,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,UAO/H;AAED,wBAAgB,gBAAgB;eAUA,KAAK,sBAAsB,QAAQ,WAAW,aAAa,CAAC,KAAK,CAAC,YAAY,eAAe;;;EAa5H;AAED,wBAAgB,sBAAsB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,QAgBvJ;AAED,wBAAgB,eAAe,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,QAwBnJ;AAED,wBAAgB,mBAAmB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,QAkBxJ;AAED,wBAAgB,qBAAqB;gCAIY,MAAM,UAAU,MAAM;;wBAa9B,KAAK,4BAA4B,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;KAAE;;EASlJ;AAED,wBAAgB,mBAAmB;sBAII,KAAK,sBAAsB,QAAQ,WAAW,aAAa,CAAC,KAAK,CAAC,aAAY,MAAM,GAAG,QAAQ,GAAG,KAAK;;;;EAmB7I"}
|
|
@@ -12,15 +12,21 @@ function isMissingOrStale(queryClient, queryKey, staleTime) {
|
|
|
12
12
|
export function useHoverPrefetch(queryKey, queryFn, options = {}) {
|
|
13
13
|
const queryClient = useQueryClient();
|
|
14
14
|
const timeoutRef = useRef(undefined);
|
|
15
|
-
const { hoverDelay = 200, enabled = true, staleTime = DEFAULT_STALE_TIME } = options;
|
|
15
|
+
const { hoverDelay = 200, enabled = true, staleTime = DEFAULT_STALE_TIME, minInterval = 1000 } = options;
|
|
16
16
|
const queryFnRef = useRef(queryFn);
|
|
17
17
|
useEffect(() => { queryFnRef.current = queryFn; }, [queryFn]);
|
|
18
|
+
const lastPrefetchRef = useRef(new Map());
|
|
18
19
|
const prefetch = useCallback(() => {
|
|
19
20
|
if (!enabled)
|
|
20
21
|
return;
|
|
22
|
+
const keyStr = JSON.stringify(queryKey);
|
|
23
|
+
const last = lastPrefetchRef.current.get(keyStr) ?? 0;
|
|
24
|
+
if (Date.now() - last < minInterval)
|
|
25
|
+
return;
|
|
21
26
|
if (!isMissingOrStale(queryClient, queryKey, staleTime))
|
|
22
27
|
return;
|
|
23
28
|
queryClient.prefetchQuery({ queryKey, queryFn: queryFnRef.current, staleTime });
|
|
29
|
+
lastPrefetchRef.current.set(keyStr, Date.now());
|
|
24
30
|
}, [queryClient, queryKey, enabled, staleTime]);
|
|
25
31
|
const handleMouseEnter = useCallback(() => {
|
|
26
32
|
if (!enabled)
|
|
@@ -40,13 +46,19 @@ export function useHoverPrefetch(queryKey, queryFn, options = {}) {
|
|
|
40
46
|
}
|
|
41
47
|
export function useRoutePrefetch() {
|
|
42
48
|
const queryClient = useQueryClient();
|
|
49
|
+
const lastPrefetchRef = useRef(new Map());
|
|
43
50
|
return useCallback((queryKey, queryFn, options) => {
|
|
44
|
-
const { enabled = true, staleTime = DEFAULT_STALE_TIME } = options || {};
|
|
51
|
+
const { enabled = true, staleTime = DEFAULT_STALE_TIME, minInterval = 1000 } = options || {};
|
|
45
52
|
if (!enabled)
|
|
46
53
|
return;
|
|
54
|
+
const keyStr = JSON.stringify(queryKey);
|
|
55
|
+
const last = lastPrefetchRef.current.get(keyStr) ?? 0;
|
|
56
|
+
if (Date.now() - last < minInterval)
|
|
57
|
+
return;
|
|
47
58
|
if (!isMissingOrStale(queryClient, queryKey, staleTime))
|
|
48
59
|
return;
|
|
49
60
|
queryClient.prefetchQuery({ queryKey, queryFn, staleTime });
|
|
61
|
+
lastPrefetchRef.current.set(keyStr, Date.now());
|
|
50
62
|
}, [queryClient]);
|
|
51
63
|
}
|
|
52
64
|
export function useBatchPrefetch() {
|
|
@@ -62,6 +74,7 @@ export function useBatchPrefetch() {
|
|
|
62
74
|
export function useSmartPrefetch() {
|
|
63
75
|
const queryClient = useQueryClient();
|
|
64
76
|
const prefetchedRef = useRef(new Set());
|
|
77
|
+
const lastPrefetchRef = useRef(new Map());
|
|
65
78
|
const shouldPrefetchQuery = useCallback((queryKey) => {
|
|
66
79
|
const key = JSON.stringify(queryKey);
|
|
67
80
|
if (prefetchedRef.current.has(key))
|
|
@@ -73,12 +86,16 @@ export function useSmartPrefetch() {
|
|
|
73
86
|
const prefetch = useCallback((queryKey, queryFn, options) => {
|
|
74
87
|
if (!shouldPrefetchQuery(queryKey))
|
|
75
88
|
return;
|
|
76
|
-
const { staleTime = DEFAULT_STALE_TIME } = options || {};
|
|
89
|
+
const { staleTime = DEFAULT_STALE_TIME, minInterval = 1000 } = options || {};
|
|
90
|
+
const keyStr = JSON.stringify(queryKey);
|
|
91
|
+
const last = lastPrefetchRef.current.get(keyStr) ?? 0;
|
|
92
|
+
if (Date.now() - last < minInterval)
|
|
93
|
+
return;
|
|
77
94
|
if (!isMissingOrStale(queryClient, queryKey, staleTime))
|
|
78
95
|
return;
|
|
79
|
-
|
|
80
|
-
prefetchedRef.current.add(key);
|
|
96
|
+
prefetchedRef.current.add(keyStr);
|
|
81
97
|
queryClient.prefetchQuery({ queryKey, queryFn, staleTime });
|
|
98
|
+
lastPrefetchRef.current.set(keyStr, Date.now());
|
|
82
99
|
}, [queryClient, shouldPrefetchQuery]);
|
|
83
100
|
const clearPrefetchHistory = useCallback(() => { prefetchedRef.current.clear(); }, []);
|
|
84
101
|
return { prefetch, shouldPrefetch: !isSlowNetwork(), clearPrefetchHistory };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { QueryClient, QueryClientProvider, useQueryClient, skipToken, useIsMutating } from "@tanstack/react-query";
|
|
2
|
-
export type { UseQueryOptions, UseSuspenseQueryOptions, UseInfiniteQueryOptions, QueryKey, MutationKey, InfiniteData } from "@tanstack/react-query";
|
|
1
|
+
export { QueryClient, QueryClientProvider, useQueryClient, skipToken, useIsMutating, useIsFetching, useQuery, useInfiniteQuery, useMutation, useSuspenseQuery, useSuspenseInfiniteQuery } from "@tanstack/react-query";
|
|
2
|
+
export type { UseQueryOptions, UseSuspenseQueryOptions, UseInfiniteQueryOptions, QueryKey, MutationKey, InfiniteData, UseQueryResult, UseInfiniteQueryResult, UseMutationResult, DefaultError } from "@tanstack/react-query";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-query/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,SAAS,EACT,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-query/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACb,MAAM,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { QueryClient, QueryClientProvider, useQueryClient, skipToken, useIsMutating } from "@tanstack/react-query";
|
|
1
|
+
export { QueryClient, QueryClientProvider, useQueryClient, skipToken, useIsMutating, useIsFetching, useQuery, useInfiniteQuery, useMutation, useSuspenseQuery, useSuspenseInfiniteQuery } from "@tanstack/react-query";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qiaopeng/tanstack-query-plus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Enhanced TanStack Query toolkit: defaults, hooks, persistence, offline, utils",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@tanstack/react-query": "^5",
|
|
76
76
|
"@tanstack/react-query-persist-client": "^5",
|
|
77
77
|
"@tanstack/react-query-devtools": "^5",
|
|
78
|
-
"react-intersection-observer": "^9"
|
|
78
|
+
"react-intersection-observer": "^9 || ^10"
|
|
79
79
|
},
|
|
80
80
|
"peerDependenciesMeta": {
|
|
81
81
|
"@tanstack/react-query-devtools": {
|