Skip to content

Commit 4c503c5

Browse files
author
Eliya Cohen
authored
fix(eslint-plugin): handle ternary expressions in queryFn (#7747)
1 parent f034d27 commit 4c503c5

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,20 @@ ruleTester.run('exhaustive-deps', rule, {
402402
}
403403
`,
404404
},
405+
{
406+
name: 'queryFn as a ternary expression with dep and a skipToken',
407+
code: normalizeIndent`
408+
import { useQuery, skipToken } from "@tanstack/react-query";
409+
const fetch = true
410+
411+
function Component({ id }) {
412+
useQuery({
413+
queryKey: [id],
414+
queryFn: fetch ? () => Promise.resolve(id) : skipToken
415+
})
416+
}
417+
`,
418+
},
405419
],
406420
invalid: [
407421
{
@@ -733,5 +747,25 @@ ruleTester.run('exhaustive-deps', rule, {
733747
},
734748
],
735749
},
750+
{
751+
name: 'should fail if queryFn is a ternary expression with missing dep and a skipToken',
752+
code: normalizeIndent`
753+
import { useQuery, skipToken } from "@tanstack/react-query";
754+
const fetch = true
755+
756+
function Component({ id }) {
757+
useQuery({
758+
queryKey: [],
759+
queryFn: fetch ? () => Promise.resolve(id) : skipToken
760+
})
761+
}
762+
`,
763+
errors: [
764+
{
765+
messageId: 'missingDeps',
766+
data: { deps: 'id' },
767+
},
768+
],
769+
},
736770
],
737771
})

packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getDocsUrl } from '../../utils/get-docs-url'
44
import { uniqueBy } from '../../utils/unique-by'
55
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
66
import { ExhaustiveDepsUtils } from './exhaustive-deps.utils'
7-
import type { TSESLint } from '@typescript-eslint/utils'
7+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils'
88
import type { ExtraRuleDocs } from '../../types'
99

1010
const QUERY_KEY = 'queryKey'
@@ -59,6 +59,7 @@ export const rule = createRule({
5959
!ASTUtils.isNodeOfOneOf(queryFn.value, [
6060
AST_NODE_TYPES.ArrowFunctionExpression,
6161
AST_NODE_TYPES.FunctionExpression,
62+
AST_NODE_TYPES.ConditionalExpression,
6263
])
6364
) {
6465
return
@@ -88,15 +89,15 @@ export const rule = createRule({
8889
const externalRefs = ASTUtils.getExternalRefs({
8990
scopeManager,
9091
sourceCode: context.sourceCode,
91-
node: queryFn.value,
92+
node: getQueryFnRelevantNode(queryFn),
9293
})
9394

9495
const relevantRefs = externalRefs.filter((reference) =>
9596
ExhaustiveDepsUtils.isRelevantReference({
9697
sourceCode: context.sourceCode,
9798
reference,
9899
scopeManager,
99-
node: queryFn.value,
100+
node: getQueryFnRelevantNode(queryFn),
100101
}),
101102
)
102103

@@ -161,3 +162,18 @@ export const rule = createRule({
161162
}
162163
}),
163164
})
165+
166+
function getQueryFnRelevantNode(queryFn: TSESTree.Property) {
167+
if (queryFn.value.type !== AST_NODE_TYPES.ConditionalExpression) {
168+
return queryFn.value
169+
}
170+
171+
if (
172+
queryFn.value.consequent.type === AST_NODE_TYPES.Identifier &&
173+
queryFn.value.consequent.name === 'skipToken'
174+
) {
175+
return queryFn.value.alternate
176+
}
177+
178+
return queryFn.value.consequent
179+
}

0 commit comments

Comments
 (0)