@hitch42/applet 0.1.1-beta.7 → 0.1.1-beta.9
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/dist/_internal/client.js +120 -11
- package/dist/_internal/log-context.d.ts +34 -0
- package/dist/_internal/log-context.js +2 -0
- package/dist/_internal/server.d.ts +14 -1
- package/dist/_internal/server.js +122 -118
- package/dist/applet.js +22 -11
- package/dist/build-Bh_S5BUv.js +2 -0
- package/dist/{build-DauirTcY.js → build-CEfFoIZZ.js} +1 -1
- package/dist/{ci-gPrwo6C0.js → ci-BKw14X2h.js} +14 -13
- package/dist/client.d.ts +3 -3
- package/dist/{contract-DB9QQhD9.d.ts → contract-CsUpTBe0.d.ts} +1 -1
- package/dist/{deploy-CqrtNJ1x.js → deploy-wGYjwXrx.js} +139 -88
- package/dist/email-DBTVhNB_.js +62 -0
- package/dist/{generate-BIifT6PK.js → generate-BEIYs17x.js} +70 -32
- package/dist/generate-Dox-OYt6.js +2 -0
- package/dist/headers-DkNr9MLJ.js +17 -0
- package/dist/index.d.ts +122 -10
- package/dist/index.js +142 -26
- package/dist/{init-Wu6XmyVc.js → init-6oGPM46R.js} +15 -17
- package/dist/{load-config-BknBkdRs.js → load-config-xEdTXs0y.js} +2 -2
- package/dist/log-context-zu8U9Sjm.js +73 -0
- package/dist/{login-iT9MRuaw.js → login-CUx3TmFQ.js} +1 -1
- package/dist/{logs-B-qZGXSK.js → logs-DSjuEN0Q.js} +20 -22
- package/dist/{manifest-C489nYUy.d.ts → manifest-C6_F4bL8.d.ts} +7 -0
- package/dist/{manifest-Bd04cWhu.js → manifest-CJSL9GuC.js} +22 -3
- package/dist/me-BW7Paary.js +32 -0
- package/dist/{project-C_rtpjp8.js → project-BRZGd6xq.js} +202 -20
- package/dist/prompt-ChS-grYO.js +29 -0
- package/dist/query-cache-CXmAyLv3.js +82 -0
- package/dist/react.d.ts +3 -2
- package/dist/react.js +98 -80
- package/dist/schedules-C8_Svr4h.js +42 -0
- package/dist/server.d.ts +9 -4
- package/dist/server.js +29 -8
- package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
- package/dist/telephony.d.ts +97 -0
- package/dist/telephony.js +726 -0
- package/dist/{upload-YbRKEqR6.d.ts → upload-DKZzz5kW.d.ts} +6 -6
- package/dist/{variables-DcwMeIau.js → variables-DT5RyHdH.js} +14 -39
- package/dist/vite.d.ts +3 -60
- package/dist/vite.js +497 -27
- package/dist/workflow-engine-BOTzURKM.js +111 -0
- package/dist/{workspace-B6lenAS5.js → workspace-D0dnnlxL.js} +37 -39
- package/package.json +18 -5
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +50 -18
- package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
- package/scaffold/.agents/skills/hitch-applets/references/files.md +3 -3
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +12 -2
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
- package/scaffold/.agents/skills/hitch-applets/references/performance.md +1 -1
- package/scaffold/.agents/skills/hitch-applets/references/records.md +27 -4
- package/scaffold/.agents/skills/hitch-applets/references/schedules.md +7 -2
- package/scaffold/.agents/skills/hitch-applets/references/server.md +0 -3
- package/scaffold/.agents/skills/hitch-applets/references/workflows.md +11 -3
- package/scaffold/.agents/skills/hitch-cli/SKILL.md +20 -20
- package/scaffold/.agents/skills/hitch-data/SKILL.md +3 -2
- package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
- package/scaffold/.agents/skills/hitch-data/references/limits.md +23 -23
- package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
- package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
- package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
- package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
- package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
- package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
- package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
- package/scaffold/.github/workflows/hitch.yml +1 -1
- package/scaffold/AGENTS.md +2 -2
- package/scaffold/applet/src/client/components/ui/alert.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/button.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/checkbox.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/dialog.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/input-group.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/select.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/sheet.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/spinner.tsx +2 -1
- package/scaffold/applet/src/client/components/ui/tabs.tsx +1 -1
- package/scaffold/applet/src/client/lib/utils.ts +1 -6
- package/scaffold/applet/src/client/styles/globals.css +2 -0
- package/dist/build-DhNDp7ji.js +0 -2
- package/dist/generate-DSk8ihsC.js +0 -2
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: core/tune-defaults-freshness-retries-and-refetching
|
|
3
|
+
description: >
|
|
4
|
+
Use this when configuring staleTime, gcTime, cache lifetime, retry, retryDelay,
|
|
5
|
+
refetchOnWindowFocus, refetchOnReconnect, refetchInterval, networkMode,
|
|
6
|
+
focusManager, onlineManager, timeoutManager, or QueryClient defaultOptions.
|
|
7
|
+
type: core
|
|
8
|
+
library: TanStack Query
|
|
9
|
+
library_version: "5.101.0"
|
|
10
|
+
requires:
|
|
11
|
+
- core/fetch-and-observe-queries
|
|
12
|
+
sources:
|
|
13
|
+
- TanStack/query:docs/framework/react/guides/important-defaults.md
|
|
14
|
+
- TanStack/query:docs/framework/react/guides/caching.md
|
|
15
|
+
- TanStack/query:docs/framework/react/guides/query-retries.md
|
|
16
|
+
- TanStack/query:docs/framework/react/guides/window-focus-refetching.md
|
|
17
|
+
- TanStack/query:docs/framework/react/guides/network-mode.md
|
|
18
|
+
- TanStack/query:docs/reference/focusManager.md
|
|
19
|
+
- TanStack/query:docs/reference/onlineManager.md
|
|
20
|
+
- TanStack/query:docs/reference/timeoutManager.md
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
27
|
+
|
|
28
|
+
export const queryClient = new QueryClient({
|
|
29
|
+
defaultOptions: {
|
|
30
|
+
queries: {
|
|
31
|
+
staleTime: 60_000,
|
|
32
|
+
gcTime: 10 * 60_000,
|
|
33
|
+
retry: 2,
|
|
34
|
+
refetchOnWindowFocus: true,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Core Patterns
|
|
41
|
+
|
|
42
|
+
### Set freshness close to the data source
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { queryOptions } from "@tanstack/react-query";
|
|
46
|
+
|
|
47
|
+
export const settingsOptions = queryOptions({
|
|
48
|
+
queryKey: ["settings"],
|
|
49
|
+
queryFn: async () => ({ theme: "system" }),
|
|
50
|
+
staleTime: 5 * 60_000,
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Disable retries in tests
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
58
|
+
|
|
59
|
+
export function createTestQueryClient() {
|
|
60
|
+
return new QueryClient({
|
|
61
|
+
defaultOptions: { queries: { retry: false } },
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Use networkMode deliberately
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { queryOptions } from "@tanstack/react-query";
|
|
70
|
+
|
|
71
|
+
export const metricsOptions = queryOptions({
|
|
72
|
+
queryKey: ["metrics"],
|
|
73
|
+
queryFn: async () => ({ count: 1 }),
|
|
74
|
+
networkMode: "online",
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Common Mistakes
|
|
79
|
+
|
|
80
|
+
### HIGH Confusing gcTime with freshness
|
|
81
|
+
|
|
82
|
+
Wrong:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { useQuery } from "@tanstack/react-query";
|
|
86
|
+
|
|
87
|
+
export function useProfile() {
|
|
88
|
+
return useQuery({
|
|
89
|
+
queryKey: ["profile"],
|
|
90
|
+
queryFn: async () => ({ name: "Tanner" }),
|
|
91
|
+
gcTime: 60_000,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Correct:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { useQuery } from "@tanstack/react-query";
|
|
100
|
+
|
|
101
|
+
export function useProfile() {
|
|
102
|
+
return useQuery({
|
|
103
|
+
queryKey: ["profile"],
|
|
104
|
+
queryFn: async () => ({ name: "Tanner" }),
|
|
105
|
+
staleTime: 60_000,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`gcTime` controls unused cache retention; `staleTime` controls whether cached data is considered fresh.
|
|
111
|
+
|
|
112
|
+
Source: TanStack/query:docs/framework/react/guides/important-defaults.md
|
|
113
|
+
|
|
114
|
+
### HIGH static staleTime blocks invalidation expectations
|
|
115
|
+
|
|
116
|
+
Wrong:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { useQuery } from "@tanstack/react-query";
|
|
120
|
+
|
|
121
|
+
export function useTodos() {
|
|
122
|
+
return useQuery({
|
|
123
|
+
queryKey: ["todos"],
|
|
124
|
+
queryFn: async () => [{ id: 1 }],
|
|
125
|
+
staleTime: "static",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Correct:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { useQuery } from "@tanstack/react-query";
|
|
134
|
+
|
|
135
|
+
export function useTodos() {
|
|
136
|
+
return useQuery({
|
|
137
|
+
queryKey: ["todos"],
|
|
138
|
+
queryFn: async () => [{ id: 1 }],
|
|
139
|
+
staleTime: 60_000,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`staleTime: 'static'` opts out of refetching even when the query is invalidated.
|
|
145
|
+
|
|
146
|
+
Source: TanStack/query:docs/framework/react/guides/important-defaults.md
|
|
147
|
+
|
|
148
|
+
### HIGH Tests hang on retries
|
|
149
|
+
|
|
150
|
+
Wrong:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
154
|
+
|
|
155
|
+
export const queryClient = new QueryClient();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Correct:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
162
|
+
|
|
163
|
+
export const queryClient = new QueryClient({
|
|
164
|
+
defaultOptions: { queries: { retry: false } },
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Default retries add delay and can make failing tests wait before surfacing errors.
|
|
169
|
+
|
|
170
|
+
Source: TanStack/query:docs/framework/react/guides/testing.md
|
|
171
|
+
|
|
172
|
+
See also: `compositions/persist-offline-and-restore-caches` for persistence rules that depend on gcTime and networkMode.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: core/understand-query-internals-and-observers
|
|
3
|
+
description: >
|
|
4
|
+
Use this when explaining or debugging TanStack Query internals: QueryClient,
|
|
5
|
+
QueryCache, MutationCache, Query, QueryObserver, active versus inactive
|
|
6
|
+
queries, observer-level options, subscriptions, stale timers, and why loaders
|
|
7
|
+
or imperative cache reads are not the same as observed queries.
|
|
8
|
+
type: core
|
|
9
|
+
library: TanStack Query
|
|
10
|
+
library_version: "5.101.0"
|
|
11
|
+
requires:
|
|
12
|
+
- core/fetch-and-observe-queries
|
|
13
|
+
sources:
|
|
14
|
+
- TanStack/query:docs/reference/QueryClient.md
|
|
15
|
+
- TanStack/query:docs/reference/QueryCache.md
|
|
16
|
+
- TanStack/query:docs/reference/QueryObserver.md
|
|
17
|
+
- TanStack/query:docs/reference/MutationCache.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Mental Model
|
|
21
|
+
|
|
22
|
+
`QueryClient` owns the caches. `QueryCache` stores `Query` instances. Hooks and adapter APIs create `QueryObserver` instances that subscribe components to one query. Observer-level options like `select`, `staleTime`, polling, and tracked result access shape what each component sees.
|
|
23
|
+
|
|
24
|
+
An inactive query can exist in the cache without active observers. It can be read imperatively, hydrated, invalidated, or garbage collected, but it is not the same as a component actively observing query state.
|
|
25
|
+
|
|
26
|
+
## Core Patterns
|
|
27
|
+
|
|
28
|
+
### Use observers for UI reads
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
function TodoPage({ id }: { id: string }) {
|
|
32
|
+
const todo = useQuery({
|
|
33
|
+
queryKey: ["todo", id],
|
|
34
|
+
queryFn: () => fetchTodo(id),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (todo.isPending) return <p>Loading...</p>;
|
|
38
|
+
if (todo.isError) return <p>{todo.error.message}</p>;
|
|
39
|
+
return <h1>{todo.data.title}</h1>;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Use QueryClient for cache orchestration
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
await queryClient.ensureQueryData(todoOptions(id));
|
|
47
|
+
queryClient.invalidateQueries({ queryKey: ["todo", id] });
|
|
48
|
+
queryClient.setQueryData(["todo", id], (old) => old && { ...old, title });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Common Mistakes
|
|
52
|
+
|
|
53
|
+
### HIGH Treating cache presence as active usage
|
|
54
|
+
|
|
55
|
+
Wrong:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const todo = queryClient.getQueryData(["todo", id]);
|
|
59
|
+
return <TodoView todo={todo} />;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Correct:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
const todo = useQuery(todoOptions(id));
|
|
66
|
+
return <TodoView todo={todo.data} />;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
UI reads should create observers so invalidation, refetch triggers, stale status, and garbage collection behave as expected.
|
|
70
|
+
|
|
71
|
+
### MEDIUM Expecting one query to have one option set
|
|
72
|
+
|
|
73
|
+
Wrong:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// assume staleTime is stored only on the Query
|
|
77
|
+
queryClient.getQueryCache().find({ queryKey })?.options.staleTime;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Correct:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const query = queryClient.getQueryCache().find({ queryKey });
|
|
84
|
+
const observerStaleTimes = query?.observers.map((observer) => observer.options.staleTime);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Several options are observer-level, so multiple components can observe the same query with different selectors or freshness behavior.
|
|
88
|
+
|
|
89
|
+
### MEDIUM Debugging without checking observer count
|
|
90
|
+
|
|
91
|
+
Wrong:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
95
|
+
// expect every cached todo query to refetch immediately
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Correct:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
queryClient.invalidateQueries({ queryKey: ["todos"], refetchType: "active" });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Inactive queries are not automatically the same as mounted queries. Check observer count in devtools when invalidation or garbage collection looks surprising.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: core/write-mutations-and-invalidate-related-queries
|
|
3
|
+
description: >
|
|
4
|
+
Use this when writing server state with useMutation, mutationFn, mutate,
|
|
5
|
+
mutateAsync, mutationKey, useMutationState, invalidateQueries, setMutationDefaults,
|
|
6
|
+
awaited invalidation, and mutation callbacks.
|
|
7
|
+
type: core
|
|
8
|
+
library: TanStack Query
|
|
9
|
+
library_version: "5.101.0"
|
|
10
|
+
requires:
|
|
11
|
+
- core/design-query-keys-and-options
|
|
12
|
+
- core/fetch-and-observe-queries
|
|
13
|
+
sources:
|
|
14
|
+
- TanStack/query:docs/framework/react/guides/mutations.md
|
|
15
|
+
- TanStack/query:docs/framework/react/guides/query-invalidation.md
|
|
16
|
+
- TanStack/query:docs/framework/react/guides/invalidations-from-mutations.md
|
|
17
|
+
- TanStack/query:docs/framework/react/guides/updates-from-mutation-responses.md
|
|
18
|
+
- TanStack/query:docs/framework/react/reference/useMutation.md
|
|
19
|
+
- TanStack/query:docs/framework/react/reference/useMutationState.md
|
|
20
|
+
- TanStack/query:docs/reference/MutationCache.md
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
27
|
+
|
|
28
|
+
export function useAddTodo() {
|
|
29
|
+
const queryClient = useQueryClient();
|
|
30
|
+
return useMutation({
|
|
31
|
+
mutationFn: async (title: string) => ({ id: Date.now(), title }),
|
|
32
|
+
onSuccess: async () => {
|
|
33
|
+
await queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Core Patterns
|
|
40
|
+
|
|
41
|
+
### Update from mutation response
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
45
|
+
|
|
46
|
+
export function useSaveTodo() {
|
|
47
|
+
const queryClient = useQueryClient();
|
|
48
|
+
return useMutation({
|
|
49
|
+
mutationFn: async (todo: { id: string; title: string }) => todo,
|
|
50
|
+
onSuccess: (todo) => {
|
|
51
|
+
queryClient.setQueryData(["todo", todo.id], todo);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Track related mutations
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { useMutationState } from "@tanstack/react-query";
|
|
61
|
+
|
|
62
|
+
export function usePendingTodoTitles() {
|
|
63
|
+
return useMutationState<string>({
|
|
64
|
+
filters: { mutationKey: ["addTodo"], status: "pending" },
|
|
65
|
+
select: (mutation) => mutation.state.variables as string,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Scope defaults by mutation key
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
74
|
+
|
|
75
|
+
export const queryClient = new QueryClient();
|
|
76
|
+
|
|
77
|
+
queryClient.setMutationDefaults(["addTodo"], {
|
|
78
|
+
mutationFn: async (title: string) => ({ id: Date.now(), title }),
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Common Mistakes
|
|
83
|
+
|
|
84
|
+
### HIGH Multiple mutate arguments
|
|
85
|
+
|
|
86
|
+
Wrong:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { useMutation } from "@tanstack/react-query";
|
|
90
|
+
|
|
91
|
+
export function useUpdateTodo() {
|
|
92
|
+
return useMutation({
|
|
93
|
+
mutationFn: async (input: { id: string; title: string }) => input,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
useUpdateTodo().mutate("1", "Ship");
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Correct:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { useMutation } from "@tanstack/react-query";
|
|
104
|
+
|
|
105
|
+
export function useUpdateTodo() {
|
|
106
|
+
return useMutation({
|
|
107
|
+
mutationFn: async (input: { id: string; title: string }) => input,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
useUpdateTodo().mutate({ id: "1", title: "Ship" });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Mutation variables are one value; pass an object when multiple fields are needed.
|
|
115
|
+
|
|
116
|
+
Source: TanStack/query:docs/framework/react/guides/mutations.md
|
|
117
|
+
|
|
118
|
+
### HIGH Per-call callback after unmount
|
|
119
|
+
|
|
120
|
+
Wrong:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { useMutation } from "@tanstack/react-query";
|
|
124
|
+
|
|
125
|
+
export function useSave() {
|
|
126
|
+
return useMutation({ mutationFn: async (title: string) => title });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
useSave().mutate("Ship", { onSuccess: () => console.log("saved") });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Correct:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { useMutation } from "@tanstack/react-query";
|
|
136
|
+
|
|
137
|
+
export function useSave() {
|
|
138
|
+
return useMutation({
|
|
139
|
+
mutationFn: async (title: string) => title,
|
|
140
|
+
onSuccess: () => console.log("saved"),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Hook-level callbacks are tied to the mutation lifecycle; per-call callbacks may not run if the observer unmounts.
|
|
146
|
+
|
|
147
|
+
Source: TanStack/query:docs/framework/react/guides/mutations.md
|
|
148
|
+
|
|
149
|
+
### HIGH Not awaiting invalidation
|
|
150
|
+
|
|
151
|
+
Wrong:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
155
|
+
|
|
156
|
+
export function useAddTodo() {
|
|
157
|
+
const queryClient = useQueryClient();
|
|
158
|
+
return useMutation({
|
|
159
|
+
mutationFn: async (title: string) => title,
|
|
160
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["todos"] }),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Correct:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
169
|
+
|
|
170
|
+
export function useAddTodo() {
|
|
171
|
+
const queryClient = useQueryClient();
|
|
172
|
+
return useMutation({
|
|
173
|
+
mutationFn: async (title: string) => title,
|
|
174
|
+
onSuccess: async () => queryClient.invalidateQueries({ queryKey: ["todos"] }),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Returning the invalidation promise keeps the mutation pending until dependent data is refreshed.
|
|
180
|
+
|
|
181
|
+
Source: TanStack/query:docs/framework/react/guides/invalidations-from-mutations.md
|
|
182
|
+
|
|
183
|
+
See also: `core/implement-optimistic-updates-and-cache-writes` for mutation side effects that update the cache before the server returns.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: framework/debug-with-devtools
|
|
3
|
+
description: >
|
|
4
|
+
Use this when adding, lazy-loading, or debugging TanStack Query devtools:
|
|
5
|
+
ReactQueryDevtools, VueQueryDevtools, SolidQueryDevtools, SvelteQueryDevtools,
|
|
6
|
+
Angular devtools panel, embedded panels, production imports, cache inspection,
|
|
7
|
+
and offline misconceptions.
|
|
8
|
+
type: framework
|
|
9
|
+
library: TanStack Query
|
|
10
|
+
framework: cross-adapter
|
|
11
|
+
library_version: "5.101.0"
|
|
12
|
+
requires:
|
|
13
|
+
- lifecycle/setup-query-client-and-providers
|
|
14
|
+
sources:
|
|
15
|
+
- TanStack/query:docs/framework/react/devtools.md
|
|
16
|
+
- TanStack/query:docs/framework/preact/devtools.md
|
|
17
|
+
- TanStack/query:docs/framework/vue/devtools.md
|
|
18
|
+
- TanStack/query:docs/framework/solid/devtools.md
|
|
19
|
+
- TanStack/query:docs/framework/svelte/devtools.md
|
|
20
|
+
- TanStack/query:docs/framework/angular/devtools.md
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
This skill builds on `lifecycle/setup-query-client-and-providers`.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
29
|
+
|
|
30
|
+
export function Devtools() {
|
|
31
|
+
return <ReactQueryDevtools initialIsOpen={false} />;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Hooks and Components
|
|
36
|
+
|
|
37
|
+
### Lazy-load production devtools
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import * as React from "react";
|
|
41
|
+
|
|
42
|
+
const ReactQueryDevtoolsProduction = React.lazy(() =>
|
|
43
|
+
import("@tanstack/react-query-devtools/production").then((module) => ({
|
|
44
|
+
default: module.ReactQueryDevtools,
|
|
45
|
+
})),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export function LazyDevtools() {
|
|
49
|
+
return (
|
|
50
|
+
<React.Suspense fallback={null}>
|
|
51
|
+
<ReactQueryDevtoolsProduction />
|
|
52
|
+
</React.Suspense>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Embed a panel
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools";
|
|
61
|
+
|
|
62
|
+
export function DevtoolsPanel() {
|
|
63
|
+
return <ReactQueryDevtoolsPanel />;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Use adapter-specific packages
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
71
|
+
import { VueQueryDevtools } from "@tanstack/vue-query-devtools";
|
|
72
|
+
|
|
73
|
+
export const devtools = { ReactQueryDevtools, VueQueryDevtools };
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Common Mistakes
|
|
77
|
+
|
|
78
|
+
### MEDIUM Eager production devtools
|
|
79
|
+
|
|
80
|
+
Wrong:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
84
|
+
|
|
85
|
+
export function AppDevtools() {
|
|
86
|
+
return <ReactQueryDevtools />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Correct:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import * as React from "react";
|
|
94
|
+
|
|
95
|
+
const Devtools = React.lazy(() =>
|
|
96
|
+
import("@tanstack/react-query-devtools/production").then((module) => ({
|
|
97
|
+
default: module.ReactQueryDevtools,
|
|
98
|
+
})),
|
|
99
|
+
);
|
|
100
|
+
export function AppDevtools() {
|
|
101
|
+
return (
|
|
102
|
+
<React.Suspense fallback={null}>
|
|
103
|
+
<Devtools />
|
|
104
|
+
</React.Suspense>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Production devtools should be lazy-loaded from the production entry.
|
|
110
|
+
|
|
111
|
+
Source: TanStack/query:docs/framework/react/devtools.md
|
|
112
|
+
|
|
113
|
+
### MEDIUM Mock offline misconception
|
|
114
|
+
|
|
115
|
+
Wrong:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
119
|
+
|
|
120
|
+
export function Devtools() {
|
|
121
|
+
return <ReactQueryDevtools initialIsOpen />;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Correct:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { onlineManager } from "@tanstack/react-query";
|
|
129
|
+
|
|
130
|
+
export function setOfflineForTest() {
|
|
131
|
+
onlineManager.setOnline(false);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Devtools inspect state; use Query managers or browser tooling to model network state.
|
|
136
|
+
|
|
137
|
+
Source: TanStack/query:docs/reference/onlineManager.md
|
|
138
|
+
|
|
139
|
+
### HIGH Devtools outside provider
|
|
140
|
+
|
|
141
|
+
Wrong:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
145
|
+
|
|
146
|
+
export function Root() {
|
|
147
|
+
return <ReactQueryDevtools />;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Correct:
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
155
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
156
|
+
|
|
157
|
+
const queryClient = new QueryClient();
|
|
158
|
+
export function Root() {
|
|
159
|
+
return (
|
|
160
|
+
<QueryClientProvider client={queryClient}>
|
|
161
|
+
<ReactQueryDevtools />
|
|
162
|
+
</QueryClientProvider>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Devtools need the same QueryClient context as the app.
|
|
168
|
+
|
|
169
|
+
Source: TanStack/query:docs/framework/react/devtools.md
|