@hitch42/applet 0.1.0-beta.10
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/LICENSE +21 -0
- package/dist/_internal/client.d.ts +7 -0
- package/dist/_internal/client.js +169 -0
- package/dist/_internal/server.d.ts +92 -0
- package/dist/_internal/server.js +181 -0
- package/dist/applet.d.ts +1 -0
- package/dist/applet.js +184 -0
- package/dist/batch-Qa4B4-Yp.d.ts +30 -0
- package/dist/build-BlmLiKro.js +90 -0
- package/dist/build-CcT-wNN9.js +2 -0
- package/dist/ci-0Q2mUh53.js +68 -0
- package/dist/client.d.ts +48 -0
- package/dist/client.js +38 -0
- package/dist/contract-QUvEGiRI.d.ts +23 -0
- package/dist/deploy-BbL3GObV.js +2579 -0
- package/dist/email-DBTVhNB_.js +62 -0
- package/dist/generate-XB-72Fzj.js +537 -0
- package/dist/generate-wIN3IYqL.js +2 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +251 -0
- package/dist/init-DwsXRUk-.js +244 -0
- package/dist/lazy-client-x0DCI98S.js +64 -0
- package/dist/load-config-OKZU3UKn.js +27 -0
- package/dist/login-BBO74hPC.js +12 -0
- package/dist/logs-XvK6Zs5Y.js +183 -0
- package/dist/manifest-4ZAc6HUk.js +191 -0
- package/dist/manifest-I-9s8R36.d.ts +88 -0
- package/dist/me-BW7Paary.js +32 -0
- package/dist/project-B0qNXnFu.js +536 -0
- package/dist/prompt-ChS-grYO.js +29 -0
- package/dist/query-cache-CXmAyLv3.js +82 -0
- package/dist/react.d.ts +37 -0
- package/dist/react.js +515 -0
- package/dist/schedules-BkWZsbSs.js +42 -0
- package/dist/server.d.ts +46 -0
- package/dist/server.js +104 -0
- package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
- package/dist/telephony.d.ts +77 -0
- package/dist/telephony.js +607 -0
- package/dist/upload-DKZzz5kW.d.ts +112 -0
- package/dist/upload-DRbVhuDm.js +114 -0
- package/dist/variables-0tjnAeut.js +108 -0
- package/dist/vite.d.ts +63 -0
- package/dist/vite.js +816 -0
- package/dist/workflow-CTo2kZF1.js +51 -0
- package/dist/workflow-DurM6Fwx.d.ts +28 -0
- package/dist/workflow-engine-MogejNfF.js +117 -0
- package/dist/workspace-DruAZPmV.js +390 -0
- package/package.json +112 -0
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +163 -0
- package/scaffold/.agents/skills/hitch-applets/references/client.md +73 -0
- package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
- package/scaffold/.agents/skills/hitch-applets/references/files.md +109 -0
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +198 -0
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +37 -0
- package/scaffold/.agents/skills/hitch-applets/references/performance.md +74 -0
- package/scaffold/.agents/skills/hitch-applets/references/records.md +176 -0
- package/scaffold/.agents/skills/hitch-applets/references/schedules.md +91 -0
- package/scaffold/.agents/skills/hitch-applets/references/server.md +95 -0
- package/scaffold/.agents/skills/hitch-applets/references/workflows.md +81 -0
- package/scaffold/.agents/skills/hitch-cli/SKILL.md +129 -0
- package/scaffold/.agents/skills/hitch-data/SKILL.md +52 -0
- package/scaffold/.agents/skills/hitch-data/references/attributes.md +127 -0
- package/scaffold/.agents/skills/hitch-data/references/limits.md +64 -0
- 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 +15 -0
- package/scaffold/AGENTS.md +38 -0
- package/scaffold/applet/components.json +25 -0
- package/scaffold/applet/src/client/components/ui/alert.tsx +73 -0
- package/scaffold/applet/src/client/components/ui/avatar.tsx +100 -0
- package/scaffold/applet/src/client/components/ui/badge.tsx +55 -0
- package/scaffold/applet/src/client/components/ui/button.tsx +90 -0
- package/scaffold/applet/src/client/components/ui/card.tsx +85 -0
- package/scaffold/applet/src/client/components/ui/checkbox.tsx +35 -0
- package/scaffold/applet/src/client/components/ui/dialog.tsx +164 -0
- package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +235 -0
- package/scaffold/applet/src/client/components/ui/input-group.tsx +144 -0
- package/scaffold/applet/src/client/components/ui/input.tsx +22 -0
- package/scaffold/applet/src/client/components/ui/label.tsx +29 -0
- package/scaffold/applet/src/client/components/ui/popover.tsx +74 -0
- package/scaffold/applet/src/client/components/ui/select.tsx +243 -0
- package/scaffold/applet/src/client/components/ui/separator.tsx +25 -0
- package/scaffold/applet/src/client/components/ui/sheet.tsx +177 -0
- package/scaffold/applet/src/client/components/ui/skeleton.tsx +13 -0
- package/scaffold/applet/src/client/components/ui/spinner.tsx +17 -0
- package/scaffold/applet/src/client/components/ui/switch.tsx +41 -0
- package/scaffold/applet/src/client/components/ui/table.tsx +114 -0
- package/scaffold/applet/src/client/components/ui/tabs.tsx +78 -0
- package/scaffold/applet/src/client/components/ui/textarea.tsx +23 -0
- package/scaffold/applet/src/client/lib/utils.ts +1 -0
- package/scaffold/applet/src/client/styles/globals.css +136 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Transitions for Non-Urgent Updates
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: maintains UI responsiveness
|
|
5
|
+
tags: rerender, transitions, startTransition, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Transitions for Non-Urgent Updates
|
|
9
|
+
|
|
10
|
+
Mark frequent, non-urgent state updates as transitions to maintain UI responsiveness.
|
|
11
|
+
|
|
12
|
+
**Incorrect (blocks UI on every scroll):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function ScrollTracker() {
|
|
16
|
+
const [scrollY, setScrollY] = useState(0);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const handler = () => setScrollY(window.scrollY);
|
|
19
|
+
window.addEventListener("scroll", handler, { passive: true });
|
|
20
|
+
return () => window.removeEventListener("scroll", handler);
|
|
21
|
+
}, []);
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (non-blocking updates):**
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { startTransition } from "react";
|
|
29
|
+
|
|
30
|
+
function ScrollTracker() {
|
|
31
|
+
const [scrollY, setScrollY] = useState(0);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const handler = () => {
|
|
34
|
+
startTransition(() => setScrollY(window.scrollY));
|
|
35
|
+
};
|
|
36
|
+
window.addEventListener("scroll", handler, { passive: true });
|
|
37
|
+
return () => window.removeEventListener("scroll", handler);
|
|
38
|
+
}, []);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use useDeferredValue for Expensive Derived Renders
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: keeps input responsive during heavy computation
|
|
5
|
+
tags: rerender, useDeferredValue, optimization, concurrent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use useDeferredValue for Expensive Derived Renders
|
|
9
|
+
|
|
10
|
+
When user input triggers expensive computations or renders, use `useDeferredValue` to keep the input responsive. The deferred value lags behind, allowing React to prioritize the input update and render the expensive result when idle.
|
|
11
|
+
|
|
12
|
+
**Incorrect (input feels laggy while filtering):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function Search({ items }: { items: Item[] }) {
|
|
16
|
+
const [query, setQuery] = useState("");
|
|
17
|
+
const filtered = items.filter((item) => fuzzyMatch(item, query));
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<input value={query} onChange={(e) => setQuery(e.target.value)} />
|
|
22
|
+
<ResultsList results={filtered} />
|
|
23
|
+
</>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Correct (input stays snappy, results render when ready):**
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
function Search({ items }: { items: Item[] }) {
|
|
32
|
+
const [query, setQuery] = useState("");
|
|
33
|
+
const deferredQuery = useDeferredValue(query);
|
|
34
|
+
const filtered = useMemo(
|
|
35
|
+
() => items.filter((item) => fuzzyMatch(item, deferredQuery)),
|
|
36
|
+
[items, deferredQuery],
|
|
37
|
+
);
|
|
38
|
+
const isStale = query !== deferredQuery;
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<input value={query} onChange={(e) => setQuery(e.target.value)} />
|
|
43
|
+
<div style={{ opacity: isStale ? 0.7 : 1 }}>
|
|
44
|
+
<ResultsList results={filtered} />
|
|
45
|
+
</div>
|
|
46
|
+
</>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**When to use:**
|
|
52
|
+
|
|
53
|
+
- Filtering/searching large lists
|
|
54
|
+
- Expensive visualizations (charts, graphs) reacting to input
|
|
55
|
+
- Any derived state that causes noticeable render delays
|
|
56
|
+
|
|
57
|
+
**Note:** Wrap the expensive computation in `useMemo` with the deferred value as a dependency, otherwise it still runs on every render.
|
|
58
|
+
|
|
59
|
+
Reference: [React useDeferredValue](https://react.dev/reference/react/useDeferredValue)
|
package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use useRef for Transient Values
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: avoids unnecessary re-renders on frequent updates
|
|
5
|
+
tags: rerender, useref, state, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use useRef for Transient Values
|
|
9
|
+
|
|
10
|
+
When a value changes frequently and you don't want a re-render on every update (e.g., mouse trackers, intervals, transient flags), store it in `useRef` instead of `useState`. Keep component state for UI; use refs for temporary DOM-adjacent values. Updating a ref does not trigger a re-render.
|
|
11
|
+
|
|
12
|
+
**Incorrect (renders every update):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function Tracker() {
|
|
16
|
+
const [lastX, setLastX] = useState(0);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const onMove = (e: MouseEvent) => setLastX(e.clientX);
|
|
20
|
+
window.addEventListener("mousemove", onMove);
|
|
21
|
+
return () => window.removeEventListener("mousemove", onMove);
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
style={{
|
|
27
|
+
position: "fixed",
|
|
28
|
+
top: 0,
|
|
29
|
+
left: lastX,
|
|
30
|
+
width: 8,
|
|
31
|
+
height: 8,
|
|
32
|
+
background: "black",
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Correct (no re-render for tracking):**
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
function Tracker() {
|
|
43
|
+
const lastXRef = useRef(0);
|
|
44
|
+
const dotRef = useRef<HTMLDivElement>(null);
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const onMove = (e: MouseEvent) => {
|
|
48
|
+
lastXRef.current = e.clientX;
|
|
49
|
+
const node = dotRef.current;
|
|
50
|
+
if (node) {
|
|
51
|
+
node.style.transform = `translateX(${e.clientX}px)`;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
window.addEventListener("mousemove", onMove);
|
|
55
|
+
return () => window.removeEventListener("mousemove", onMove);
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
ref={dotRef}
|
|
61
|
+
style={{
|
|
62
|
+
position: "fixed",
|
|
63
|
+
top: 0,
|
|
64
|
+
left: 0,
|
|
65
|
+
width: 8,
|
|
66
|
+
height: 8,
|
|
67
|
+
background: "black",
|
|
68
|
+
transform: "translateX(0px)",
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tanstack-query
|
|
3
|
+
description: Build, review, debug, test, or migrate TanStack Query code. Use for server state, query keys, mutations, cache behavior, pagination, hydration, persistence, and framework adapters.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# TanStack Query
|
|
8
|
+
|
|
9
|
+
TanStack Query manages server state through a framework-neutral cache, observers, adapters, persistence tools, devtools, lint rules, and migration tools.
|
|
10
|
+
|
|
11
|
+
TanStack Start and TanStack Router are primary composition targets. Use them for loaders, SSR hydration, streaming, and cache handoff.
|
|
12
|
+
|
|
13
|
+
## Use
|
|
14
|
+
|
|
15
|
+
1. Inspect the installed TanStack Query version and framework adapter.
|
|
16
|
+
2. Select one primary reference from the domain index.
|
|
17
|
+
3. Read another reference only when a listed tension or cross-reference applies.
|
|
18
|
+
4. Preserve types from query options, mutation options, and library APIs.
|
|
19
|
+
5. Run the relevant tests, type check, and lint checks after a change.
|
|
20
|
+
|
|
21
|
+
## Domain Index
|
|
22
|
+
|
|
23
|
+
### Bootstrapping query clients
|
|
24
|
+
|
|
25
|
+
- [Set up QueryClient and providers](references/lifecycle/setup-query-client-and-providers.md)
|
|
26
|
+
|
|
27
|
+
### Reading server state
|
|
28
|
+
|
|
29
|
+
- [Design query keys and reusable options](references/core/design-query-keys-and-options.md)
|
|
30
|
+
- [Build Query abstractions](references/core/build-query-abstractions.md)
|
|
31
|
+
- [Understand Query internals and observers](references/core/understand-query-internals-and-observers.md)
|
|
32
|
+
- [Fetch and observe queries](references/core/fetch-and-observe-queries.md)
|
|
33
|
+
- [Handle status checks and errors](references/framework/handle-status-and-errors.md)
|
|
34
|
+
|
|
35
|
+
### Coordinating query execution
|
|
36
|
+
|
|
37
|
+
- [Tune defaults, freshness, retries, and refetching](references/core/tune-defaults-freshness-retries-and-refetching.md)
|
|
38
|
+
- [Coordinate dependent, parallel, disabled, and background queries](references/core/coordinate-query-execution.md)
|
|
39
|
+
- [Paginate and build infinite queries](references/core/paginate-and-build-infinite-queries.md)
|
|
40
|
+
|
|
41
|
+
### Writing server state
|
|
42
|
+
|
|
43
|
+
- [Write mutations and invalidate related queries](references/core/write-mutations-and-invalidate-related-queries.md)
|
|
44
|
+
- [Apply automatic invalidation after mutations](references/compositions/automatic-invalidation-after-mutations.md)
|
|
45
|
+
- [Implement optimistic updates and cache writes](references/core/implement-optimistic-updates-and-cache-writes.md)
|
|
46
|
+
- [Handle concurrent optimistic updates](references/core/concurrent-optimistic-updates.md)
|
|
47
|
+
- [Use Query data in forms](references/compositions/query-data-and-forms.md)
|
|
48
|
+
- [Cancel queries and consume AbortSignals](references/core/cancel-queries-and-consume-abort-signals.md)
|
|
49
|
+
|
|
50
|
+
### Shaping cache and render behavior
|
|
51
|
+
|
|
52
|
+
- [Seed, use placeholder data, select, and transform data](references/core/seed-placeholder-select-and-transform-data.md)
|
|
53
|
+
- [Use selectors and derived state](references/core/selectors-and-derived-state.md)
|
|
54
|
+
- [Shape data and render efficiently](references/framework/shape-data-and-render-efficiently.md)
|
|
55
|
+
|
|
56
|
+
### Rendering across environments
|
|
57
|
+
|
|
58
|
+
- [Prefetch and remove request waterfalls](references/lifecycle/prefetch-and-remove-request-waterfalls.md)
|
|
59
|
+
- [Compose Query with TanStack Router and Start](references/compositions/compose-query-with-tanstack-router-and-start.md)
|
|
60
|
+
- [Use SSR, hydration, and streaming](references/lifecycle/ssr-hydration-and-streaming.md)
|
|
61
|
+
- [Use Suspense and error boundaries](references/framework/use-suspense-and-error-boundaries.md)
|
|
62
|
+
|
|
63
|
+
### Persisting and synchronizing caches
|
|
64
|
+
|
|
65
|
+
- [Persist offline and restore caches](references/compositions/persist-offline-and-restore-caches.md)
|
|
66
|
+
- [Use broadcast, realtime, and multi-tab synchronization](references/compositions/broadcast-realtime-and-multi-tab-synchronization.md)
|
|
67
|
+
|
|
68
|
+
### Framework adapter idioms
|
|
69
|
+
|
|
70
|
+
- [Use framework adapter reactivity](references/framework/use-framework-adapter-reactivity.md)
|
|
71
|
+
|
|
72
|
+
### Operational quality
|
|
73
|
+
|
|
74
|
+
- [Debug with devtools](references/framework/debug-with-devtools.md)
|
|
75
|
+
- [Test Query code](references/lifecycle/test-query-code.md)
|
|
76
|
+
- [Migrate major versions and codemods](references/lifecycle/migrate-major-versions-and-codemods.md)
|
|
77
|
+
- [Enforce Query best practices with ESLint](references/compositions/enforce-query-best-practices-with-eslint.md)
|
|
78
|
+
|
|
79
|
+
## Failure Mode Inventory
|
|
80
|
+
|
|
81
|
+
| Reference | Check for |
|
|
82
|
+
| ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| [QueryClient setup](references/lifecycle/setup-query-client-and-providers.md) | A new client on each render; a shared SSR cache between users; an ambiguous Lit fallback client |
|
|
84
|
+
| [Query keys and options](references/core/design-query-keys-and-options.md) | Missing variables in a query key; key and query function drift; skipToken in a Suspense query |
|
|
85
|
+
| [Query abstractions](references/core/build-query-abstractions.md) | A custom hook as the only abstraction; wide options wrappers; hidden Query result state |
|
|
86
|
+
| [Query internals](references/core/understand-query-internals-and-observers.md) | Cache presence treated as active use; ignored observer options; inactive queries expected to refetch |
|
|
87
|
+
| [Fetch and observe](references/core/fetch-and-observe-queries.md) | A void query function; pending-only offline checks; queries used for writes |
|
|
88
|
+
| [Status and errors](references/framework/handle-status-and-errors.md) | Hidden stale data on a background error; validation errors sent to a global boundary; duplicate observer toasts |
|
|
89
|
+
| [Defaults and freshness](references/core/tune-defaults-freshness-retries-and-refetching.md) | gcTime used as freshness; static staleTime blocking invalidation; test delays from retries |
|
|
90
|
+
| [Query coordination](references/core/coordinate-query-execution.md) | Imperative disabled queries; duplicate useQueries keys; full-page spinners during background refetch |
|
|
91
|
+
| [Pagination](references/core/paginate-and-build-infinite-queries.md) | A missing initialPageParam; overlapping infinite fetches; an invalid pages and pageParams shape |
|
|
92
|
+
| [Mutations and invalidation](references/core/write-mutations-and-invalidate-related-queries.md) | Multiple mutate arguments; per-call callbacks after unmount; invalidation that is not awaited |
|
|
93
|
+
| [Automatic invalidation](references/compositions/automatic-invalidation-after-mutations.md) | Full-app invalidation for each mutation; an unreturned invalidation promise; refetches for static data |
|
|
94
|
+
| [Optimistic updates](references/core/implement-optimistic-updates-and-cache-writes.md) | A write without cancellation; an in-place mutation; a persisted optimistic write that is lost |
|
|
95
|
+
| [Concurrent optimistic updates](references/core/concurrent-optimistic-updates.md) | One invalidation that reverts another write; filter mismatch; unstable pending row keys |
|
|
96
|
+
| [Query data and forms](references/compositions/query-data-and-forms.md) | Form defaults before query data; a refetch that overwrites dirty state; duplicate submission |
|
|
97
|
+
| [Cancellation](references/core/cancel-queries-and-consume-abort-signals.md) | An ignored AbortSignal; an assumption that unmount cancels work; expected Suspense cancellation |
|
|
98
|
+
| [Seed and transform data](references/core/seed-placeholder-select-and-transform-data.md) | An initialData overwrite assumption; the removed keepPreviousData option; errors thrown in select |
|
|
99
|
+
| [Selectors](references/core/selectors-and-derived-state.md) | Effect-based state sync; an inline expensive selector; errors thrown in select |
|
|
100
|
+
| [Render efficiency](references/framework/shape-data-and-render-efficiently.md) | Rest destructuring; a query result object in hook dependencies; Vue v-model on immutable data |
|
|
101
|
+
| [Prefetch](references/lifecycle/prefetch-and-remove-request-waterfalls.md) | prefetchQuery expected to return data; staleTime only on prefetch; Suspense prefetch in an effect |
|
|
102
|
+
| [Router and Start](references/compositions/compose-query-with-tanstack-router-and-start.md) | Component-only route waterfalls; custom Router hydration; copied Next.js assumptions |
|
|
103
|
+
| [SSR and streaming](references/lifecycle/ssr-hydration-and-streaming.md) | RSC rendering fetched data twice; an unprefetched Suspense query; a late SvelteKit query |
|
|
104
|
+
| [Suspense](references/framework/use-suspense-and-error-boundaries.md) | A disabled Suspense query; a missing reset boundary; query.promise without its feature flag |
|
|
105
|
+
| [Persistence](references/compositions/persist-offline-and-restore-caches.md) | gcTime below maxAge; rendering before restore; a missing default mutation function |
|
|
106
|
+
| [Broadcast and realtime](references/compositions/broadcast-realtime-and-multi-tab-synchronization.md) | Uncontrolled experimental broadcast; over-normalized writes; server-side broadcast |
|
|
107
|
+
| [Adapter reactivity](references/framework/use-framework-adapter-reactivity.md) | An unwrapped Vue ref; Svelte store syntax in v6; a directly returned Angular Observable |
|
|
108
|
+
| [Devtools](references/framework/debug-with-devtools.md) | Eager production devtools; offline simulation treated as network control; devtools outside the provider |
|
|
109
|
+
| [Tests](references/lifecycle/test-query-code.md) | A shared test client; retry backoff in tests; assertions before asynchronous success |
|
|
110
|
+
| [Migration](references/lifecycle/migrate-major-versions-and-codemods.md) | v4 overload syntax; removed query callbacks; cacheTime in v5 |
|
|
111
|
+
| [ESLint](references/compositions/enforce-query-best-practices-with-eslint.md) | A missing strict rule; invalid infinite option order; invalid mutation option order |
|
|
112
|
+
|
|
113
|
+
## Tensions
|
|
114
|
+
|
|
115
|
+
| Tension | Read together | Apply |
|
|
116
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
117
|
+
| Declarative cache and imperative fetch control | [Query coordination](references/core/coordinate-query-execution.md), [fetch and observe](references/core/fetch-and-observe-queries.md) | Prefer query keys and enabled state to manual refetch flows. |
|
|
118
|
+
| SSR freshness and user data isolation | [QueryClient setup](references/lifecycle/setup-query-client-and-providers.md), [Router and Start](references/compositions/compose-query-with-tanstack-router-and-start.md), [SSR](references/lifecycle/ssr-hydration-and-streaming.md), [freshness](references/core/tune-defaults-freshness-retries-and-refetching.md) | Isolate server caches and prevent duplicate hydration fetches. |
|
|
119
|
+
| Router loading and component queries | [Prefetch](references/lifecycle/prefetch-and-remove-request-waterfalls.md), [Router and Start](references/compositions/compose-query-with-tanstack-router-and-start.md), [Query internals](references/core/understand-query-internals-and-observers.md) | Prefetch in loaders and keep Query as the server-state owner. |
|
|
120
|
+
| Optimistic response and server truth | [Optimistic updates](references/core/implement-optimistic-updates-and-cache-writes.md), [concurrent updates](references/core/concurrent-optimistic-updates.md), [invalidation](references/core/write-mutations-and-invalidate-related-queries.md), [persistence](references/compositions/persist-offline-and-restore-caches.md) | Include cancellation, rollback, invalidation, concurrency guards, and persistence rules. |
|
|
121
|
+
| Reuse and type preservation | [Query keys](references/core/design-query-keys-and-options.md), [abstractions](references/core/build-query-abstractions.md), [selectors](references/core/selectors-and-derived-state.md) | Prefer option factories that preserve selection inference and work in loaders. |
|
|
122
|
+
| Automatic invalidation and scoped freshness | [Automatic invalidation](references/compositions/automatic-invalidation-after-mutations.md), [mutations](references/core/write-mutations-and-invalidate-related-queries.md), [freshness](references/core/tune-defaults-freshness-retries-and-refetching.md) | Scope invalidation with mutation keys, metadata, and static-data exclusions. |
|
|
123
|
+
| Form ownership and server freshness | [Forms](references/compositions/query-data-and-forms.md), [selectors](references/core/selectors-and-derived-state.md), [mutations](references/core/write-mutations-and-invalidate-related-queries.md) | Keep dirty fields while useful server updates continue. |
|
|
124
|
+
| Framework idioms and React examples | [Adapter reactivity](references/framework/use-framework-adapter-reactivity.md), [query keys](references/core/design-query-keys-and-options.md), [SSR](references/lifecycle/ssr-hydration-and-streaming.md) | Preserve the selected adapter's reactivity model. |
|
|
125
|
+
|
|
126
|
+
## Cross-References
|
|
127
|
+
|
|
128
|
+
- Read [SSR, hydration, and streaming](references/lifecycle/ssr-hydration-and-streaming.md) with [QueryClient setup](references/lifecycle/setup-query-client-and-providers.md). Client lifetime differs between browsers and servers.
|
|
129
|
+
- Read [ESLint](references/compositions/enforce-query-best-practices-with-eslint.md) with [query keys and options](references/core/design-query-keys-and-options.md). The rules detect key and option errors.
|
|
130
|
+
- Read [Query abstractions](references/core/build-query-abstractions.md) with [query keys and options](references/core/design-query-keys-and-options.md). Option factories join reusable keys and query functions.
|
|
131
|
+
- Read [status and errors](references/framework/handle-status-and-errors.md), [Query internals](references/core/understand-query-internals-and-observers.md), and [defaults](references/core/tune-defaults-freshness-retries-and-refetching.md) with [fetch and observe](references/core/fetch-and-observe-queries.md).
|
|
132
|
+
- Read [optimistic updates](references/core/implement-optimistic-updates-and-cache-writes.md), [automatic invalidation](references/compositions/automatic-invalidation-after-mutations.md), and [concurrent updates](references/core/concurrent-optimistic-updates.md) with [mutations](references/core/write-mutations-and-invalidate-related-queries.md).
|
|
133
|
+
- Read [cancellation](references/core/cancel-queries-and-consume-abort-signals.md) before an optimistic write that can conflict with a refetch.
|
|
134
|
+
- Read [selectors](references/core/selectors-and-derived-state.md) with [seed and transform data](references/core/seed-placeholder-select-and-transform-data.md), [forms](references/compositions/query-data-and-forms.md), and [abstractions](references/core/build-query-abstractions.md).
|
|
135
|
+
- Read [Router and Start](references/compositions/compose-query-with-tanstack-router-and-start.md) with [prefetch](references/lifecycle/prefetch-and-remove-request-waterfalls.md), [SSR](references/lifecycle/ssr-hydration-and-streaming.md), and [Suspense](references/framework/use-suspense-and-error-boundaries.md).
|
|
136
|
+
- Read [defaults](references/core/tune-defaults-freshness-retries-and-refetching.md) with [persistence](references/compositions/persist-offline-and-restore-caches.md). Persistence depends on gcTime, networkMode, and retry behavior.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compositions/automatic-invalidation-after-mutations
|
|
3
|
+
description: >
|
|
4
|
+
Use this when designing automatic invalidation policies for TanStack Query
|
|
5
|
+
mutations with MutationCache callbacks, mutationKey-to-queryKey matching,
|
|
6
|
+
mutation meta invalidation tags, awaited invalidation, and exclusions for
|
|
7
|
+
static or unrelated queries.
|
|
8
|
+
type: composition
|
|
9
|
+
library: TanStack Query
|
|
10
|
+
library_version: "5.101.0"
|
|
11
|
+
requires:
|
|
12
|
+
- core/write-mutations-and-invalidate-related-queries
|
|
13
|
+
- core/design-query-keys-and-options
|
|
14
|
+
sources:
|
|
15
|
+
- TanStack/query:docs/framework/react/guides/invalidations-from-mutations.md
|
|
16
|
+
- TanStack/query:docs/reference/MutationCache.md
|
|
17
|
+
- TanStack/query:docs/reference/QueryClient.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Core Patterns
|
|
21
|
+
|
|
22
|
+
Use local mutation callbacks for one-off behavior. Use `MutationCache` callbacks when the app wants a consistent invalidation policy for every mutation.
|
|
23
|
+
|
|
24
|
+
### Global invalidation after successful mutations
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { MutationCache, QueryClient } from "@tanstack/react-query";
|
|
28
|
+
|
|
29
|
+
export const queryClient = new QueryClient({
|
|
30
|
+
mutationCache: new MutationCache({
|
|
31
|
+
onSuccess: (_data, _variables, _context, mutation) => {
|
|
32
|
+
return queryClient.invalidateQueries({
|
|
33
|
+
queryKey: mutation.options.mutationKey,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If a mutation has `mutationKey: ['issues']`, this invalidates matching issue queries. If it has no mutation key, this becomes a broad invalidation policy, so only use that deliberately.
|
|
41
|
+
|
|
42
|
+
### Use meta for explicit invalidation tags
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { matchQuery, MutationCache, QueryClient } from "@tanstack/react-query";
|
|
46
|
+
|
|
47
|
+
const queryClient = new QueryClient({
|
|
48
|
+
mutationCache: new MutationCache({
|
|
49
|
+
onSuccess: (_data, _variables, _context, mutation) => {
|
|
50
|
+
return queryClient.invalidateQueries({
|
|
51
|
+
predicate: (query) =>
|
|
52
|
+
mutation.meta?.invalidates?.some((queryKey) => matchQuery({ queryKey }, query)) ?? true,
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Common Mistakes
|
|
60
|
+
|
|
61
|
+
### HIGH Invalidating the whole app for every mutation
|
|
62
|
+
|
|
63
|
+
Wrong:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
new MutationCache({
|
|
67
|
+
onSuccess: () => queryClient.invalidateQueries(),
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Correct:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
new MutationCache({
|
|
75
|
+
onSuccess: (_data, _variables, _context, mutation) =>
|
|
76
|
+
queryClient.invalidateQueries({ queryKey: mutation.options.mutationKey }),
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Global policies need scope. Reach for mutation keys or meta tags before invalidating everything.
|
|
81
|
+
|
|
82
|
+
### HIGH Not returning invalidation when pending UI depends on refetch
|
|
83
|
+
|
|
84
|
+
Wrong:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
onSuccess: () => {
|
|
88
|
+
queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Correct:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Returning the promise keeps the mutation pending until the invalidation refetch completes.
|
|
99
|
+
|
|
100
|
+
Source: TanStack/query:docs/framework/react/guides/invalidations-from-mutations.md
|
|
101
|
+
|
|
102
|
+
### MEDIUM Refetching data that should be static
|
|
103
|
+
|
|
104
|
+
Wrong:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
useQuery({
|
|
108
|
+
queryKey: ["build-info"],
|
|
109
|
+
queryFn: fetchBuildInfo,
|
|
110
|
+
staleTime: Infinity,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Correct:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
useQuery({
|
|
118
|
+
queryKey: ["build-info"],
|
|
119
|
+
queryFn: fetchBuildInfo,
|
|
120
|
+
staleTime: "static",
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
If a query must not refetch even after broad manual invalidation, mark it with `staleTime: 'static'`.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compositions/broadcast-realtime-and-multi-tab-synchronization
|
|
3
|
+
description: >
|
|
4
|
+
Use this when synchronizing TanStack Query caches with broadcastQueryClient,
|
|
5
|
+
BroadcastChannel, multi-tab cache sync, realtime invalidation, WebSocket
|
|
6
|
+
events, server/browser boundaries, and experimental broadcast behavior.
|
|
7
|
+
type: composition
|
|
8
|
+
library: TanStack Query
|
|
9
|
+
library_version: "5.101.0"
|
|
10
|
+
requires:
|
|
11
|
+
- lifecycle/setup-query-client-and-providers
|
|
12
|
+
- core/write-mutations-and-invalidate-related-queries
|
|
13
|
+
- compositions/persist-offline-and-restore-caches
|
|
14
|
+
sources:
|
|
15
|
+
- TanStack/query:docs/framework/react/plugins/broadcastQueryClient.md
|
|
16
|
+
- TanStack/query:docs/framework/react/guides/query-invalidation.md
|
|
17
|
+
- TanStack/query:examples/react/chat/package.json
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
24
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
25
|
+
|
|
26
|
+
export const queryClient = new QueryClient();
|
|
27
|
+
|
|
28
|
+
if (typeof window !== "undefined") {
|
|
29
|
+
broadcastQueryClient({ queryClient, broadcastChannel: "app-query-cache" });
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Core Integration Patterns
|
|
34
|
+
|
|
35
|
+
### Invalidate from realtime events
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
39
|
+
|
|
40
|
+
const queryClient = new QueryClient();
|
|
41
|
+
|
|
42
|
+
export function onTodoChanged(todoId: number) {
|
|
43
|
+
return queryClient.invalidateQueries({ queryKey: ["todo", todoId] });
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Update narrow cache slices
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
51
|
+
|
|
52
|
+
const queryClient = new QueryClient();
|
|
53
|
+
|
|
54
|
+
export function onTodoTitle(todo: { id: number; title: string }) {
|
|
55
|
+
queryClient.setQueryData(["todo", todo.id], todo);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Keep broadcast client-side
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
63
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
64
|
+
|
|
65
|
+
export function installBroadcast(queryClient: QueryClient) {
|
|
66
|
+
if (typeof window === "undefined") return;
|
|
67
|
+
broadcastQueryClient({ queryClient, broadcastChannel: "query-cache" });
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Common Mistakes
|
|
72
|
+
|
|
73
|
+
### MEDIUM Unlocked experimental broadcast
|
|
74
|
+
|
|
75
|
+
Wrong:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
79
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
80
|
+
|
|
81
|
+
broadcastQueryClient({ queryClient: new QueryClient() });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Correct:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
88
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
89
|
+
|
|
90
|
+
if (typeof window !== "undefined") {
|
|
91
|
+
broadcastQueryClient({
|
|
92
|
+
queryClient: new QueryClient(),
|
|
93
|
+
broadcastChannel: "query-cache-v1",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The broadcast package is experimental and should be deliberately isolated behind browser-only setup.
|
|
99
|
+
|
|
100
|
+
Source: TanStack/query:docs/framework/react/plugins/broadcastQueryClient.md
|
|
101
|
+
|
|
102
|
+
### MEDIUM Over-normalized realtime writes
|
|
103
|
+
|
|
104
|
+
Wrong:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
108
|
+
|
|
109
|
+
const queryClient = new QueryClient();
|
|
110
|
+
queryClient.setQueryData(["todos"], { byId: { 1: { id: 1 } }, allIds: [1] });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Correct:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
117
|
+
|
|
118
|
+
const queryClient = new QueryClient();
|
|
119
|
+
queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Query is not a normalized cache; invalidation is often safer than duplicating server state models.
|
|
123
|
+
|
|
124
|
+
Source: TanStack/query:docs/framework/react/guides/query-invalidation.md
|
|
125
|
+
|
|
126
|
+
### HIGH Broadcast on server
|
|
127
|
+
|
|
128
|
+
Wrong:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
132
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
133
|
+
|
|
134
|
+
export const queryClient = new QueryClient();
|
|
135
|
+
broadcastQueryClient({ queryClient });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Correct:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
142
|
+
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
|
|
143
|
+
|
|
144
|
+
export const queryClient = new QueryClient();
|
|
145
|
+
if (typeof window !== "undefined") broadcastQueryClient({ queryClient });
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
BroadcastChannel is a browser primitive; server setup should not install it.
|
|
149
|
+
|
|
150
|
+
Source: TanStack/query:docs/framework/react/plugins/broadcastQueryClient.md
|