Skip to content

fix(eslint-plugin-query): ignore call targets in exhaustive-deps#11067

Open
Newbie012 wants to merge 3 commits into
TanStack:mainfrom
Newbie012:fix-exhaustive-deps-call-targets
Open

fix(eslint-plugin-query): ignore call targets in exhaustive-deps#11067
Newbie012 wants to merge 3 commits into
TanStack:mainfrom
Newbie012:fix-exhaustive-deps-call-targets

Conversation

@Newbie012

@Newbie012 Newbie012 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Related discussion: #11062

🎯 Changes

The exhaustive-deps rule no longer requires function call targets in query keys. Query keys should contain the serializable values that identify the returned data, not functions or API clients.

// 🟢 `todoId` identifies the query.
// `fetchTodoById` does not need to be in the query key.
useQuery({
  queryKey: ['todo', todoId],
  queryFn: () => fetchTodoById(todoId),
})

Values used inside nested callbacks are still checked:

// 🔴 Reports `todoId` as missing.
useQuery({
  queryKey: ['todo'],
  queryFn: () => Promise.resolve().then(() => todoId),
})

Computed method names are also checked because they can change the returned data:

// 🔴 Reports `operation` as missing.
useQuery({
  queryKey: ['data'],
  queryFn: () => client[operation](),
})

The documentation now describes query keys as serializable data identifiers and updates the examples to match.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally. All 1,709 ESLint plugin tests and ESLint checks pass.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes

    • Improved the exhaustive-deps ESLint rule: query keys no longer need to include function call targets, while values referenced within nested callbacks are still required.
    • Refined member-access handling, including optional chaining, computed properties, and non-null assertions.
  • Documentation

    • Updated guidance and examples for constructing React Query queryKeys with only the serializable values that identify the data.
  • Tests

    • Expanded and adjusted rule and AST utility tests to reflect the updated dependency analysis behavior.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d1a4444-ce2c-4a4c-914c-a2343b27f837

📥 Commits

Reviewing files that changed from the base of the PR and between bd1e2a5 and 9be3cd8.

📒 Files selected for processing (1)
  • packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts

📝 Walkthrough

Walkthrough

The exhaustive-deps rule now ignores function call targets when deriving query-key dependencies, while continuing to validate referenced values. AST traversal, tests, documentation, and changeset metadata were updated accordingly.

Changes

Exhaustive-deps call-target handling

Layer / File(s) Summary
Member-expression reference traversal
packages/eslint-plugin-query/src/utils/ast-utils.ts, packages/eslint-plugin-query/src/__tests__/ast-utils.test.ts
Adds traversal for chained member expressions and handles computed member paths used as call targets, with focused utility coverage.
Call-target dependency filtering
packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts
Excludes function and method call targets from dependencies and updates full-chain path computation.
Behavior validation and release documentation
packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts, docs/eslint/exhaustive-deps.md, .changeset/soft-pianos-sip.md
Updates rule cases, dependency suggestions, guidance, and patch-release metadata for the revised behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ESLintAST
  participant ASTUtils
  participant ExhaustiveDepsUtils
  participant RuleTests
  ESLintAST->>ASTUtils: Resolve member-expression references
  ASTUtils-->>ExhaustiveDepsUtils: Return reference paths
  ExhaustiveDepsUtils->>ExhaustiveDepsUtils: Exclude function call targets
  ExhaustiveDepsUtils-->>RuleTests: Report remaining missing dependencies
Loading

Suggested labels: package: eslint-plugin-query

Suggested reviewers: tkdodo

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change to exhaustive-deps behavior.
Description check ✅ Passed The description follows the required template and includes the changes, checklist, and release impact sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Newbie012
Newbie012 marked this pull request as ready for review July 15, 2026 15:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts (1)

319-330: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove dead code.

With the introduction of isFunctionCallTarget, any identifier that resolves to a CallExpression callee is now completely filtered out upstream inside isRelevantReference. Consequently, fullChainNode will never be a CallExpression callee here, making this if block mathematically unreachable.

You can safely remove this logic that previously stripped method names from dependencies.

♻️ Proposed refactor
-    if (
-      parent &&
-      parent.type === AST_NODE_TYPES.CallExpression &&
-      parent.callee === fullChainNode
-    ) {
-      const segments = fullText.split('.')
-      if (segments.length > 1) {
-        dependencyPath = segments.slice(0, -1).join('.')
-      }
-
-      coversRootMembers = false
-    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts`
around lines 319 - 330, Remove the unreachable parent CallExpression check
comparing parent.callee with fullChainNode from the dependency-path logic in the
surrounding utility function. Delete its segments/dependencyPath adjustment and
coversRootMembers assignment, while preserving the remaining reference
processing unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/eslint-plugin-query/src/utils/ast-utils.ts`:
- Around line 146-159: Guard all AST parent accesses before reading .type or
recursing: in packages/eslint-plugin-query/src/utils/ast-utils.ts lines 146-159,
update traverseUpMemberExpression to require parent before inspecting it; in
packages/eslint-plugin-query/src/utils/ast-utils.ts lines 201-215, update
getExternalRefs to handle undefined memberExpression and
memberExpression.parent; and in
packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts
lines 64-71, update isFunctionCallTarget to guard callee.parent. Preserve
existing traversal behavior for defined nodes.

---

Nitpick comments:
In
`@packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts`:
- Around line 319-330: Remove the unreachable parent CallExpression check
comparing parent.callee with fullChainNode from the dependency-path logic in the
surrounding utility function. Delete its segments/dependencyPath adjustment and
coversRootMembers assignment, while preserving the remaining reference
processing unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4e4bf5a-33be-4a2c-a727-5ce45e15a09c

📥 Commits

Reviewing files that changed from the base of the PR and between 79d2384 and 365258b.

📒 Files selected for processing (5)
  • .changeset/soft-pianos-sip.md
  • docs/eslint/exhaustive-deps.md
  • packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts
  • packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts
  • packages/eslint-plugin-query/src/utils/ast-utils.ts

Comment thread packages/eslint-plugin-query/src/utils/ast-utils.ts
@nx-cloud

nx-cloud Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit bd1e2a5

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 2m 40s View ↗
nx run-many --target=build --exclude=examples/*... ❌ Failed 1m 57s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-15 15:43:49 UTC

@TkDodo

TkDodo commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

seems like a legit failure:

/home/runner/work/query/query/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts (58,49): Argument of type 'Identifier | JSXIdentifier' is not assignable to parameter of type 'Identifier'.
  Type 'JSXIdentifier' is missing the following properties from type 'Identifier': decorators, optional, typeAnnotation
Error: TypeScript compilation failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants