react-doctor/query-destructure-result
Destructure the query result instead of binding the whole object: const { data, isLoading } = useQuery(...)
- Category: Bugs
- Severity: warn
- Source:
oxlint-plugin-react-doctor - Framework: tanstack-query
- Enabled when: framework=tanstack-query and capabilities=tanstack-query
- Tags: test-noise
- Default: Enabled
- Documentation: https://tanstack.com/query/latest/docs/framework/react/guides/render-optimizations
Validate the diagnostic
Confirm the reported code matches this rule before you edit it.
Fires on a VariableDeclarator whose id is a plain Identifier (not an ObjectPattern/ArrayPattern) and whose init is a CallExpression whose callee is itself an Identifier matching one of the four TANSTACK_QUERY_HOOKS: useQuery, useInfiniteQuery, useSuspenseQuery, useSuspenseInfiniteQuery — i.e. const query = useQuery(...) where the whole result is captured under one name. It does NO scope or usage analysis: it reports unconditionally on that shape regardless of how the binding is later used. Only two real exclusions, both structural: already-destructured (node.id is an ObjectPattern or ArrayPattern, so const { data } = useQuery(...) never matches), and a callee that is not literally one of those four Identifiers (a member-expression call like queryClient.fetchQuery, a wrapper hook of your own, or a same-named local Identifier that is not the TanStack import). False positive is a reviewer judgment, not a detector suppression: the rule still fires when the whole object must legitimately be held as one value (forwarded as-is to a child, returned untouched from a custom hook, or kept to spread later) — suppress those manually.
How to fix
Follow the rule guidance while preserving unrelated behavior.
Copyable fix prompt
Copy this self-contained prompt into your coding agent after you confirm the diagnostic.
Related rules
More Bugs rules from the rules reference:
react-doctor/query-floating-mutate-async: Floating mutateAsync rejectionreact-doctor/query-mutation-missing-invalidation: Add `onSuccess: () => queryClient.invalidateQueries({ queryKey: ['...'] })` so cached data stays in sync after the mutationreact-doctor/query-no-mutation-in-effect-as-read: Mutation driven from an effect as a readreact-doctor/query-no-query-in-effect: React Query manages refetching automatically via queryKey dependencies and the `enabled` option — manual refetch() in useEffect is usually unnecessaryreact-doctor/query-no-rest-destructuring: Destructure only the fields you need: `const { data, isLoading } = useQuery(...)` — rest destructuring subscribes to all fields and causes extra re-renders