ESLint plugin to enforce best practices when working with TanStack Query
npm install eslint-plugin-react-query-must-invalidate-queries --save-dev
# or
yarn add eslint-plugin-react-query-must-invalidate-queries --dev
# or
pnpm add eslint-plugin-react-query-must-invalidate-queries --save-dev
# or
bun add eslint-plugin-react-query-must-invalidate-queries --dev
Add react-query-must-invalidate-queries
to the plugins section of your .eslintrc
configuration file:
{
"plugins": ["react-query-must-invalidate-queries"],
"rules": {
"react-query-must-invalidate-queries/require-mutation-invalidation": "error" // or "warn"
}
}
You can see a real world config here using this: https://github.com/ayinke-llc/malak/blob/main/web/ui/eslint.config.mjs
🔧 This rule enforces that useMutation
hooks include an onSuccess
callback that
calls invalidateQueries
to ensure data consistency.
When using mutations in React Query, it's important to invalidate related queries after a successful mutation to ensure the UI reflects the latest server state without having to do a lot of mental prep.
This rule helps prevent stale data by ensuring that mutations properly invalidate affected queries.
This rule enforces:
- Presence of an
onSuccess
callback inuseMutation
hooks - The
onSuccess
callback must include a call toinvalidateQueries
✅ Examples of correct code:
useMutation({
mutationFn: updateUser,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
useMutation({
mutationFn: updateUser,
onSuccess: () => {
const { invalidateQueries } = queryClient;
invalidateQueries({ queryKey: ["users"] });
},
});
useMutation({
mutationFn: updateUser,
onSuccess: async () => {
await someOtherOperation();
await queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
❌ Examples of incorrect code:
useMutation({
mutationFn: updateUser,
});
useMutation({
mutationFn: updateUser,
onSuccess: () => {
console.log("Success!");
},
});
useMutation({
mutationFn: updateUser,
onSuccess: () => {},
});
You might want to disable this rule if:
- You have mutations that intentionally don't need to invalidate any queries
- You're handling cache updates through other means like
setQueryData
- You have a specific caching strategy that doesn't require query invalidation
Contributions are welcome! Please read our contributing guidelines to get started.
MIT