Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
a341931
add @tanstack/eslint-plugin-query
Newbie012 Oct 23, 2022
b0a6732
fix .eslintrc rule name
Newbie012 Oct 23, 2022
758bb61
Merge branch 'main' into feature-eslint-plugin
TkDodo Oct 23, 2022
0b3d91c
make rule compatible with babel parser
Newbie012 Oct 23, 2022
b30209f
fix script typo
Newbie012 Oct 23, 2022
7a22b6f
remove dedicated example in favor of the basic example
Newbie012 Oct 23, 2022
23a447c
align package version with the other packages
Newbie012 Oct 23, 2022
8f41031
align eslint-plugin-query version
Newbie012 Oct 23, 2022
a6af4a9
fix displayName
Newbie012 Oct 23, 2022
f2f2c0a
remove typescript from package
Newbie012 Oct 23, 2022
4da87d9
omit call expressions from keys without the need of whitelist
Newbie012 Oct 23, 2022
4d571ee
lint queryKey instead of useQuery
Newbie012 Oct 23, 2022
3f7e1c7
update pnpm-lock.yaml
Newbie012 Oct 23, 2022
b7fba1a
Merge branch 'feature-eslint-plugin' of https://github.com/Newbie012/…
Newbie012 Oct 23, 2022
dc8c0eb
fix auto-fix suggestion for complex ast
Newbie012 Oct 24, 2022
59214a8
better inline query key
Newbie012 Oct 24, 2022
a78f85f
fix typo
Newbie012 Oct 24, 2022
776bca6
update scripts
Newbie012 Oct 25, 2022
6a71436
restore .eslintrc
Newbie012 Oct 25, 2022
02a062c
update typescript-eslint packages
Newbie012 Oct 25, 2022
1c38511
support member expression keys
Newbie012 Oct 25, 2022
eaee66b
format
Newbie012 Oct 25, 2022
e0b4f9f
should not fix with duplicate keys
Newbie012 Oct 25, 2022
64a7e7a
Merge branch 'main' into feature-eslint-plugin
Newbie012 Oct 25, 2022
df3a802
format
Newbie012 Oct 26, 2022
ab94f9a
Merge branch 'feature-eslint-plugin' of https://github.com/Newbie012/…
Newbie012 Oct 26, 2022
e8c2632
empty commit (flaky test)
Newbie012 Oct 27, 2022
fdaa6a6
should ignore keys from callback
Newbie012 Oct 30, 2022
535be2c
Update packages/eslint-plugin-query/package.json
Newbie012 Oct 30, 2022
afd006e
Merge branch 'main' into feature-eslint-plugin
TkDodo Oct 30, 2022
3e1f2b6
add prefer-query-object-syntax rule
Newbie012 Oct 30, 2022
0170633
Merge branch 'feature-eslint-plugin' of https://github.com/Newbie012/…
Newbie012 Oct 30, 2022
432017f
fix indention
Newbie012 Oct 30, 2022
96d9192
fix headline
Newbie012 Oct 30, 2022
616b156
Merge branch 'main' into feature-eslint-plugin
TkDodo Nov 1, 2022
eba0444
Merge branch 'main' into feature-eslint-plugin
Newbie012 Nov 1, 2022
bc4c70a
add rule description
TkDodo Nov 1, 2022
5501dbc
Merge branch 'main' into feature-eslint-plugin
TkDodo Nov 1, 2022
c83ae52
fix lint errors
TkDodo Nov 1, 2022
260d231
widen import check for all adapters
Newbie012 Nov 1, 2022
d8f6dfe
add support for solid-query (createQuery)
Newbie012 Nov 1, 2022
405cd8b
Merge branch 'feature-eslint-plugin' of https://github.com/Newbie012/…
Newbie012 Nov 1, 2022
253ced7
docs: add eslint plugin section
TkDodo Nov 1, 2022
47192a7
prettier
TkDodo Nov 1, 2022
176d662
move docs
TkDodo Nov 1, 2022
348f461
EsLint -> ESLint
TkDodo Nov 1, 2022
58bb647
fix typo
TkDodo Nov 1, 2022
7f961d2
add missing dep
TkDodo Nov 1, 2022
3551295
update lockfile
Newbie012 Nov 1, 2022
6ec2643
give credit where credit is due
TkDodo Nov 1, 2022
350f057
Merge branch 'main' into feature-eslint-plugin
TkDodo Nov 1, 2022
25b969b
Merge branch 'main' into feature-eslint-plugin
TkDodo Nov 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,23 @@
}
]
},
{
"label": "ESLint",
"children": [
{
"label": "ESLint Plugin Query",
"to": "eslint/eslint-plugin-query"
},
{
"label": "Exhaustive Deps",
"to": "eslint/exhaustive-deps"
},
{
"label": "prefer-query-object-syntax",
"to": "eslint/prefer-query-object-syntax"
}
]
},
{
"label": "Plugins",
"children": [
Expand Down
49 changes: 49 additions & 0 deletions docs/eslint/eslint-plugin-query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
id: eslint-plugin-query
title: ESLint Plugin Query
---

TanStack Query comes with its own ESLint plugin. This plugin is used to enforce best practices and to help you avoid common mistakes.

## Installation

The plugin is a separate package that you need to install:

```bash
$ npm i @tanstack/eslint-plugin-query
# or
$ pnpm add @tanstack/eslint-plugin-query
# or
$ yarn add @tanstack/eslint-plugin-query
```

## Usage

Add `@tanstack/eslint-plugin-query` to the plugins section of your `.eslintrc` configuration file:

```json
{
"plugins": ["@tanstack/query"]
}
```

Then configure the rules you want to use under the rules section:

```json
{
"rules": {
"@tanstack/query/exhaustive-deps": "error",
"@tanstack/query/prefer-query-object-syntax": "error"
}
}
```

### Recommended config

You can also enable all the recommended rules for our plugin. Add `plugin:@tanstack/eslint-plugin-query/recommended` in extends:

```json
{
"extends": ["plugin:@tanstack/eslint-plugin-query/recommended"]
}
```
47 changes: 47 additions & 0 deletions docs/eslint/exhaustive-deps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
id: exhaustive-deps
title: Exhaustive dependencies for query keys
---

Query keys should be seen like a dependency array to your query function: Every variable that is used inside the queryFn should be added to the query key.
This makes sure that queries are cached independently and that queries are refetched automatically when the variables changes.

## Rule Details

Examples of **incorrect** code for this rule:

```ts
/* eslint "@tanstack/query/exhaustive-deps": "error" */

useQuery({
queryKey: ["todo"],
queryFn: () => api.getTodo(todoId)
})

const todoQueries = {
detail: (id) => ({ queryKey: ["todo"], queryFn: () => api.getTodo(id) })
}
```


Examples of **correct** code for this rule:

```ts
useQuery({
queryKey: ["todo", todoId],
queryFn: () => api.getTodo(todoId)
})

const todoQueries = {
detail: (id) => ({ queryKey: ["todo", id], queryFn: () => api.getTodo(id) })
}
```

## When Not To Use It

If you don't care about the rules of the query keys, then you will not need this rule.

## Attributes

- [x] ✅ Recommended
- [x] 🔧 Fixable
62 changes: 62 additions & 0 deletions docs/eslint/prefer-query-object-syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
id: prefer-query-object-syntax
title: Prefer object syntax for useQuery
---

You can use [`useQuery`](https://tanstack.com/query/v4/docs/reference/useQuery) in two different ways.

Standard

```ts
useQuery(queryKey, queryFn?, options?)

// or

useQuery(options)
```

This rule prefers the second option, as it is more consistent with other React Query hooks, like `useQueries`. It will also be the only available option in a future major version.

## Rule Details

Examples of **incorrect** code for this rule:

```js
/* eslint "@tanstack/query/prefer-query-object-syntax": "error" */

import { useQuery } from '@tanstack/react-query';

useQuery(queryKey, queryFn, {
onSuccess,
});

useQuery(queryKey, {
queryFn,
onSuccess,
});
```

Examples of **correct** code for this rule:

```js
import { useQuery } from '@tanstack/react-query';

useQuery({
queryKey,
queryFn,
onSuccess,
});
```

## When Not To Use It

If you don't care about useQuery consistency, then you will not need this rule.

## Attributes

- [x] ✅ Recommended
- [x] 🔧 Fixable

## Credits

This rule was initially developed by [KubaJastrz](https://github.com/KubaJastrz) in [eslint-plugin-react-query](https://github.com/KubaJastrz/eslint-plugin-react-query).
6 changes: 1 addition & 5 deletions examples/react/basic-typescript/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{
"extends": ["react-app", "prettier"],
"rules": {
// "eqeqeq": 0,
// "jsx-a11y/anchor-is-valid": 0
}
"extends": ["react-app", "prettier", "plugin:@tanstack/eslint-plugin-query/recommended"]
}
1 change: 1 addition & 0 deletions examples/react/basic-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@tanstack/query-sync-storage-persister": "^4.7.1"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "^4.13.0",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@vitejs/plugin-react": "^2.0.0",
Expand Down
6 changes: 1 addition & 5 deletions examples/react/basic/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{
"extends": ["react-app", "prettier"],
"rules": {
// "eqeqeq": 0,
// "jsx-a11y/anchor-is-valid": 0
}
"extends": ["react-app", "prettier", "plugin:@tanstack/eslint-plugin-query/recommended"]
}
7 changes: 4 additions & 3 deletions examples/react/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
"preview": "vite preview"
},
"dependencies": {
"@tanstack/react-query": "^4.7.1",
"@tanstack/react-query-devtools": "^4.7.1",
"axios": "^0.21.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"@tanstack/react-query": "^4.7.1",
"@tanstack/react-query-devtools": "^4.7.1"
"react-dom": "^18.0.0"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "^4.13.0",
"@vitejs/plugin-react": "^2.0.0",
"vite": "^3.0.0"
},
Expand Down
17 changes: 11 additions & 6 deletions examples/react/basic/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ function App() {
}

function usePosts() {
return useQuery(["posts"], async () => {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
return data;
return useQuery({
queryKey: ["posts"],
queryFn: async () => {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
return data;
},
});
}

Expand Down Expand Up @@ -98,7 +101,9 @@ const getPostById = async (id) => {
};

function usePost(postId) {
return useQuery(["post", postId], () => getPostById(postId), {
return useQuery({
queryKey: ["post", postId],
queryFn: () => getPostById(postId),
enabled: !!postId,
});
}
Expand Down
1 change: 1 addition & 0 deletions examples/solid/simple/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"extends": ["plugin:@tanstack/eslint-plugin-query/recommended"],
"parserOptions": {
"project": "./tsconfig.json",
"sourceType": "module"
Expand Down
1 change: 1 addition & 0 deletions examples/solid/simple/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"solid-js": "^1.5.1"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "^4.13.0",
"typescript": "^4.8.2",
"vite": "^3.0.9",
"vite-plugin-solid": "^2.3.9"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"@types/testing-library__jest-dom": "^5.14.5",
"@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^5.6.0",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"axios": "^0.26.1",
"babel-eslint": "^10.1.0",
"babel-jest": "^27.5.1",
Expand Down
7 changes: 7 additions & 0 deletions packages/eslint-plugin-query/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"sourceType": "module"
}
}
4 changes: 4 additions & 0 deletions packages/eslint-plugin-query/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
displayName: 'eslint-plugin-query',
preset: '../../jest-preset.js',
}
44 changes: 44 additions & 0 deletions packages/eslint-plugin-query/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@tanstack/eslint-plugin-query",
"version": "4.13.0",
"description": "ESLint plugin for TanStack Query",
"author": "Eliya Cohen",
"license": "MIT",
"repository": "tanstack/query",
"homepage": "https://tanstack.com/query",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"main": "build/lib/index.js",
"scripts": {
"typecheck": "tsc",
"build": "tsup --minify",
"dev": "tsup --watch --sourcemap",
"clean": "rm -rf ./build",
"test:jest": "../../node_modules/.bin/jest --config ./jest.config.ts",
"test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src",
"test:dev": "pnpm run test:jest --watch"
},
"files": [
"build"
],
"tsup": {
"entry": [
"src/index.ts"
],
"external": [
"eslint"
],
"clean": true,
"bundle": true,
"outDir": "build/lib"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"@typescript-eslint/utils": "^5.41.0",
"eslint": "^8.26.0",
"tsup": "^6.3.0"
}
}
19 changes: 19 additions & 0 deletions packages/eslint-plugin-query/src/configs/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { configs } from './index'

describe('configs', () => {
it('should match snapshot', () => {
expect(configs).toMatchInlineSnapshot(`
{
"recommended": {
"plugins": [
"@tanstack/eslint-plugin-query",
],
"rules": {
"@tanstack/query/exhaustive-deps": "error",
"@tanstack/query/prefer-query-object-syntax": "error",
},
},
}
`)
})
})
22 changes: 22 additions & 0 deletions packages/eslint-plugin-query/src/configs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { TSESLint } from '@typescript-eslint/utils'
import { rules } from '../rules'

function generateRecommendedConfig(
allRules: Record<string, TSESLint.RuleModule<any, any>>,
) {
return Object.entries(allRules).reduce((memo, [name, rule]) => {
const { recommended } = rule.meta.docs || {}

return {
...memo,
...(recommended ? { [`@tanstack/query/${name}`]: recommended } : {}),
}
}, {} as Record<string, 'strict' | 'error' | 'warn'>)
}

export const configs = {
recommended: {
plugins: ['@tanstack/eslint-plugin-query'],
rules: generateRecommendedConfig(rules),
},
}
2 changes: 2 additions & 0 deletions packages/eslint-plugin-query/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { configs } from './configs'
export { rules } from './rules'
Loading