Skip to content

Conversation

DDShantanuBadmanji
Copy link

@DDShantanuBadmanji DDShantanuBadmanji commented Oct 13, 2025

Summary by CodeRabbit

  • New Features
    • Added a new hook, useQueryState, now publicly available to retrieve aggregated query state with flexible filtering and selection.
  • Refactor
    • Streamlined useIsFetching to use shared query state logic for more consistent fetching counts.
    • Optimized mutation state updates to reduce unnecessary re-renders and batch notifications for smoother UI updates.
  • Tests
    • Improved test components and scenarios to ensure stable rendering behavior when tracking fetching and mutation states.

Copy link

Summary of Changes

Hello @DDShantanuBadmanji, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a powerful new useQueryState hook, designed to provide a more generic and efficient way to access and react to changes within the QueryCache. By centralizing state observation and deep equality checks, this hook streamlines how query states are managed. The existing useIsFetching hook has been refactored to utilize this new foundation, showcasing its practical application and simplifying its codebase. Additionally, the useMutationState hook's internal subscription logic has been updated to mirror these new patterns, ensuring consistency and potentially improving performance across the library's state-observing hooks.

Highlights

  • New useQueryState Hook: Introduced a new useQueryState hook that allows users to observe and retrieve query states from the QueryCache based on provided filters. This hook centralizes logic for reacting to cache changes and includes deep equality checks to prevent unnecessary re-renders.
  • Refactored useIsFetching: The useIsFetching hook has been completely rewritten to leverage the newly introduced useQueryState hook, simplifying its implementation and demonstrating the utility of the new generic state observation mechanism.
  • Improved useMutationState Subscription: The internal useSyncExternalStore implementation within useMutationState has been refined. It now uses notifyManager.batchCalls for subscriptions and incorporates the replaceEqualDeep logic directly into the snapshot function, aligning with patterns used in the new useQueryState hook for consistent state management.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

coderabbitai bot commented Oct 13, 2025

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title “Clone use query state” does not clearly reflect the primary changes in the pull request, which include adding a new useQueryState hook and refactoring useIsFetching and useMutationState to use it; the phrase is vague and does not describe the main functional update. Rename the title to something more descriptive, for example “Add useQueryState hook and refactor useIsFetching to leverage it,” so that it clearly summarizes the main functionality introduced and refactored.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch clone-use-query-state

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 and usage tips.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new useQueryState hook, which is then used to simplify the implementation of useIsFetching. This is a great abstraction that improves code reuse. The related changes in useMutationState and the tests are also solid improvements. I have one suggestion regarding the new useQueryState hook to enhance its type safety.

Comment on lines +33 to +36
export function useQueryState<TResult = QueryState>(
options: QueryStateOptions<TResult> = {},
queryClient?: QueryClient,
): Array<TResult> {

Choose a reason for hiding this comment

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

medium

The current typings for useQueryState can lead to type-safety issues. If a consumer provides a generic type for TResult but omits the select function, the hook will return an array of QueryState objects that are incorrectly typed as TResult[]. This can lead to runtime errors that are not caught by the TypeScript compiler.

To improve type safety, I recommend using function overloads to ensure that if a custom TResult is specified, a select function returning that type is also required. This pattern is used elsewhere in React Query and would make this new API more robust.

Copy link

@coderabbitai coderabbitai bot left a comment

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/react-query/src/useQueryState.ts (1)

44-46: Nit: align optionsRef update semantics with useMutationState

To avoid edge cases where options are mutated in place (identity doesn’t change), consider removing the dependency array so the ref updates every render, matching useMutationState.

-  React.useEffect(() => {
-    optionsRef.current = options
-  }, [options])
+  React.useEffect(() => {
+    optionsRef.current = options
+  })
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a5990e and efa8623.

📒 Files selected for processing (6)
  • packages/react-query/src/__tests__/useIsFetching.test.tsx (1 hunks)
  • packages/react-query/src/__tests__/useMutationState.test.tsx (3 hunks)
  • packages/react-query/src/index.ts (1 hunks)
  • packages/react-query/src/useIsFetching.ts (1 hunks)
  • packages/react-query/src/useMutationState.ts (1 hunks)
  • packages/react-query/src/useQueryState.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
packages/react-query/src/__tests__/useMutationState.test.tsx (2)
packages/query-core/src/queryClient.ts (1)
  • isMutating (107-109)
packages/react-query/src/useMutationState.ts (1)
  • useIsMutating (15-24)
packages/react-query/src/useIsFetching.ts (2)
packages/query-core/src/queryClient.ts (1)
  • QueryClient (54-550)
packages/react-query/src/useQueryState.ts (1)
  • useQueryState (33-67)
packages/react-query/src/useQueryState.ts (2)
packages/query-core/src/types.ts (2)
  • DefaultError (18-22)
  • QueryKey (24-24)
packages/react-query/src/index.ts (2)
  • useQueryState (43-43)
  • useQueryClient (31-31)
packages/react-query/src/__tests__/useIsFetching.test.tsx (2)
packages/query-core/src/queryClient.ts (1)
  • isFetching (102-105)
packages/react-query/src/useIsFetching.ts (1)
  • useIsFetching (5-13)
🪛 GitHub Actions: pr
packages/react-query/src/useQueryState.ts

[error] 39-39: src/useQueryState.ts(39,24): TS2554: Expected 1 arguments, but got 0.

🔇 Additional comments (7)
packages/react-query/src/index.ts (1)

43-43: Expose useQueryState: LGTM

New public export looks correct and consistent with internal usage.

Please add a brief entry to changelog/docs for the new public hook.

packages/react-query/src/__tests__/useIsFetching.test.tsx (1)

208-209: Inline isFetching with custom client: LGTM

Correctly scopes isFetching and uses the provided queryClient.

packages/react-query/src/__tests__/useMutationState.test.tsx (1)

69-77: Memoizing test component to isolate renders: LGTM

Using React.memo avoids unrelated re-renders from sibling hooks, stabilizing expected sequences.

Also applies to: 110-120

packages/react-query/src/useMutationState.ts (1)

67-67: Batched subscription + structural sharing: LGTM

  • notifyManager.batchCalls in subscribe reduces redundant renders.
  • replaceEqualDeep + ref memoization avoids useless updates.

Also applies to: 70-81

packages/react-query/src/useQueryState.ts (1)

48-66: Approve subscription and snapshot logic

  • Batching via notifyManager.batchCalls(onStoreChange) is correct
  • replaceEqualDeep with ref memoization ensures stable identities and minimal re-renders
packages/react-query/src/useIsFetching.ts (2)

2-2: LGTM!

The import of useQueryState is correct and aligns with the refactored implementation.


9-12: LGTM! Clean refactor to useQueryState.

The implementation correctly delegates to useQueryState and returns the count of fetching queries. The spread operator on line 10 ensures fetchStatus is always set to 'fetching', which is the expected behavior for this hook.

Comment on lines +39 to +42
const result = React.useRef<Array<TResult>>()
if (!result.current) {
result.current = getResult(queryCache, options)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Build break: useRef called without initial value (TS2554)

TS error matches pipeline: Expected 1 arguments, but got 0. Initialize the ref to null (or undefined) and keep the first‑render assignment.

Apply this diff:

-  const result = React.useRef<Array<TResult>>()
+  const result = React.useRef<Array<TResult> | null>(null)
   if (!result.current) {
     result.current = getResult(queryCache, options)
   }

This preserves runtime behavior and fixes typing by using non-null assertion on the hook return.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const result = React.useRef<Array<TResult>>()
if (!result.current) {
result.current = getResult(queryCache, options)
}
const result = React.useRef<Array<TResult> | null>(null)
if (!result.current) {
result.current = getResult(queryCache, options)
}
🧰 Tools
🪛 GitHub Actions: pr

[error] 39-39: src/useQueryState.ts(39,24): TS2554: Expected 1 arguments, but got 0.

🤖 Prompt for AI Agents
In packages/react-query/src/useQueryState.ts around lines 39 to 42, useRef is
called with no initial value which breaks TS (expects 1 arg); change the ref to
be initialized to null (e.g., useRef<Array<TResult> | null>(null)) so typing is
satisfied, keep the existing first-render assignment result.current =
getResult(...), and use a non-null assertion when reading result.current later
(result.current!) to preserve runtime behavior and satisfy TypeScript.

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.

4 participants