react-doctor/query-mutation-missing-invalidation
Add `onSuccess: () => queryClient.invalidateQueries({ queryKey: ['...'] })` so cached data stays in sync after the mutation
- Category: TanStack Query
- Severity: warn
- Source:
oxlint-plugin-react-doctor - Framework: tanstack-query
- Enabled when: framework=tanstack-query and capabilities=tanstack-query
Validation prompt
Use this to decide whether a fired diagnostic is real or a false positive.
Fires on useMutation({ mutationFn: ..., ... }) when the options object nowhere contains a member call whose property is invalidateQueries, setQueryData, setQueriesData, resetQueries, refetchQueries, removeQueries, cancelQueries, or clear. The walker searches the entire options tree (onSuccess/onSettled/onError/optimisticUpdate). False positive: invalidation lives in a parent router.refresh() or a global mutation success handler.
Fix prompt
Use this once validation confirms the diagnostic is real.
Add onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }) inside the options (or setQueryData for an optimistic update, resetQueries for a hard reset). Always use the object form { queryKey: [...] } — the deprecated string-key signature won't match and stale data lingers. https://tanstack.com/query/latest/docs/framework/react/guides/invalidations-from-mutations
Related rules
More TanStack Query rules from the rules reference:
react-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-rendersreact-doctor/query-no-usequery-for-mutation: Use `useMutation()` for POST/PUT/DELETE — it provides onSuccess/onError callbacks, doesn't auto-refetch, and correctly models write operationsreact-doctor/query-no-void-query-fn: queryFn must return a value for the cache. Use the `enabled` option to conditionally disable the query instead of returning undefinedreact-doctor/query-stable-query-client: Move `new QueryClient()` to module scope or wrap in `useState(() => new QueryClient())` — recreating it on every render resets the entire cache