react-query-best-practices
Skill1 starsChanged 2 months agoApache-2.0View on GitHub
Audit React Query usage for best practices — key factories, staleTime, mutations, and server state ownership
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 5 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Read these before analyzing:
- Very specific: line 29
Every file in hooks/queries/ must have a hierarchical key factory with an all root key
- Very specific: line 34
Every queryFn must forward signal for request cancellation
- Very specific: line 35
Every query must have an explicit staleTime (default 0 is almost never correct), assigned from a named exported constant — never an inline …
- Very specific: line 37
Use enabled to prevent queries from running without required params
- Very specific: line 40
Use onSettled (not onSuccess) for cache reconciliation — it fires on both success and error
- Very specific: line 42
Use targeted invalidation (entityKeys.lists()) not broad (entityKeys.all) when possible
- Very specific: line 43
Don't include mutation objects in useCallback deps — .mutate() is stable
- Distinctive: line 46
Never copy query data into useState.
- Distinctive: line 47
Never copy query data into Zustand stores (exception: mutation callbacks that coordinate cross-store state like temp ID replacement)
- Distinctive: line 53
Read the references above to understand the guidelines
- Distinctive: line 55
If fix=true, apply the fixes.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
React Query Best Practices
Arguments:
- scope: what to analyze (default: your current changes). Examples: "diff to main", "PR #123", "src/hooks/queries/", "whole codebase"
- fix: whether to apply fixes (default: true). Set to false to only propose changes.
User arguments: $ARGUMENTS
Context
This codebase uses React Query (TanStack Query) as the single source of truth for all server state. All query hooks live in hooks/queries/. Zustand is used only for client-only UI state. Server data must never be duplicated into useState or Zustand outside of mutation callbacks that coordinate cross-store state.
References
Read these before analyzing:
- https://tkdodo.eu/blog/practical-react-query — foundational defaults, custom hooks, avoiding local state copies
- https://tkdodo.eu/blog/effective-react-query-keys — key factory pattern, hierarchical keys, fuzzy invalidation
- https://tkdodo.eu/blog/react-query-as-a-state-manager — React Query IS your server state manager
Rules to enforce
Query key factories
- Every file in
hooks/queries/must have a hierarchical key factory with anallroot key - Keys must include intermediate plural keys (
lists,details) for prefix invalidation - Key factories are colocated with their query hooks, not in a global keys file
Query hooks
- Every
queryFnmust forwardsignalfor request cancellation - Every query must have an explicit
staleTime(default 0 is almost never correct), assigned from a named exported constant — never an inline numeric literal. A server-side prefetch hydrating the same query key must import and reuse that constant instead of restating the number keepPreviousData/placeholderDataonly on variable-key queries (where params change), never on static keys- Use
enabledto prevent queries from running without required params
Mutations
- Use
onSettled(notonSuccess) for cache reconciliation — it fires on both success and error - For optimistic updates: save previous data in
onMutate, roll back inonError - Use targeted invalidation (
entityKeys.lists()) not broad (entityKeys.all) when possible - Don't include mutation objects in
useCallbackdeps —.mutate()is stable
Server state ownership
- Never copy query data into useState. Use query data directly in components.
- Never copy query data into Zustand stores (exception: mutation callbacks that coordinate cross-store state like temp ID replacement)
- The query cache is not a local state manager —
setQueryDatais for optimistic updates only - Forms are the one deliberate exception: copy server data into local form state with
staleTime: Infinity
Steps
- Read the references above to understand the guidelines
- Analyze the specified scope against the rules listed above
- If fix=true, apply the fixes. If fix=false, propose the fixes without applying.
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 1
- simstudioai/sim★ 30k37% same
Wrote their own version · 1
- bibektimilsina00/runmycrew★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository54 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/constitution.mdcCursor rule
- .cursor/rules/emcn-components.mdcCursor rule
- .cursor/rules/global.mdcCursor rule
- .cursor/rules/landing-seo-geo.mdcCursor rule
- .cursor/rules/sim-architecture.mdcCursor rule
- .cursor/rules/sim-components.mdcCursor rule
- .cursor/rules/sim-hooks.mdcCursor rule
- .cursor/rules/sim-imports.mdcCursor rule
- .cursor/rules/sim-integrations.mdcCursor rule
- .cursor/rules/sim-queries.mdcCursor rule
- .cursor/rules/sim-sandbox.mdcCursor rule
- .cursor/rules/sim-stores.mdcCursor rule
- .cursor/rules/sim-styling.mdcCursor rule
- .cursor/rules/sim-testing.mdcCursor rule
- .cursor/rules/sim-typescript.mdcCursor rule
- .cursor/rules/sim-ui-copy.mdcCursor rule
- add-block-previewSkill
- add-blockSkill
- add-column-typeSkill
- add-connectorSkill
- add-enrichmentSkill
- add-feature-flagSkill
- add-hosted-keySkill
- add-integrationSkill
- add-managed-cliSkill
- add-modelSkill
- add-toolsSkill
- add-triggerSkill
- babysitSkill
- cleanupSkill
- councilSkill
- db-migrateSkill
- design-taste-frontendSkill
- emcn-design-reviewSkill
- emil-design-engSkill
- make-interfaces-feel-betterSkill
- memory-load-checkSkill
- migrate-application-operationSkill
- shipSkill
- tool-registry-boundarySkill
- v2-api-conventionsSkill
- validate-connectorSkill
- validate-integrationSkill
- validate-modelSkill
- validate-triggerSkill
- you-might-not-need-a-callbackSkill
- you-might-not-need-a-commentSkill
- you-might-not-need-a-memoSkill
- you-might-not-need-an-effectSkill
- you-might-not-need-stateSkill
- you-might-not-need-url-stateSkill
- add-settings-pageSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

