Skip to content

Conversation

@sukvvon
Copy link
Contributor

@sukvvon sukvvon commented Dec 14, 2025

🎯 Changes

Fixes #9610

When using HydrationBoundary with existing queries in the cache, an unnecessary refetch was triggered during hydration even though fresh data was about to be hydrated from the server.

Root Cause

  • useQuery's onSubscribe runs before HydrationBoundary's useEffect completes hydration
  • The query appears stale (before hydration), triggering an unnecessary refetch

Solution

  • Added pendingHydrationQueries WeakSet to track queries pending hydration
  • Mark existing queries as pending in useMemo (before children render)
  • Skip refetch in queryObserver.onSubscribe if query is pending hydration
  • Exception: refetchOnMount: 'always' still triggers refetch (user explicitly wants fresh data)
  • Clear pending flag in useEffect after hydration completes
  • Added cleanup function to clear pending flags on unmount

Files Changed

  • packages/query-core/src/hydration.ts - Export pendingHydrationQueries WeakSet
  • packages/query-core/src/index.ts - Re-export pendingHydrationQueries
  • packages/query-core/src/queryObserver.ts - Check pending hydration in onSubscribe
  • packages/react-query/src/HydrationBoundary.tsx - Mark/clear pending hydration queries with cleanup
  • packages/react-query/src/__tests__/HydrationBoundary.test.tsx - Add 14 test cases
  • docs/framework/react/guides/ssr.md - Document new behavior
  • docs/framework/react/reference/hydration.md - Document new behavior

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 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

  • New Features

    • Added useIsHydrating hook and IsHydratingProvider to track hydration state.
    • HydrationBoundary now intelligently prevents unnecessary refetches when hydrated data is fresh.
  • Bug Fixes

    • Fixed double-fetching issues during hydration with improved staleTime handling.
  • Documentation

    • Updated SSR guide with hydration-aware refetch behavior and server memory considerations.
    • Enhanced hydration reference with clarifications on automatic refetch prevention.
  • Tests

    • Added comprehensive hydration test coverage for various scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Dec 14, 2025

🦋 Changeset detected

Latest commit: bb9cced

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@tanstack/query-core Patch
@tanstack/react-query Patch
@tanstack/angular-query-experimental Patch
@tanstack/query-async-storage-persister Patch
@tanstack/query-broadcast-client-experimental Patch
@tanstack/query-persist-client-core Patch
@tanstack/query-sync-storage-persister Patch
@tanstack/solid-query Patch
@tanstack/svelte-query Patch
@tanstack/vue-query Patch
@tanstack/react-query-devtools Patch
@tanstack/react-query-next-experimental Patch
@tanstack/react-query-persist-client Patch
@tanstack/angular-query-persist-client Patch
@tanstack/solid-query-persist-client Patch
@tanstack/svelte-query-persist-client Patch
@tanstack/solid-query-devtools Patch
@tanstack/svelte-query-devtools Patch
@tanstack/vue-query-devtools Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

📝 Walkthrough

Walkthrough

This PR fixes double-fetching during hydration by introducing hydration-aware refetch prevention. When HydrationBoundary hydrates queries with fresh data, the system now tracks pending hydration status and skips unnecessary refetches on mount unless explicitly requested via refetchOnMount: 'always'.

Changes

Cohort / File(s) Summary
Changeset & Documentation
.changeset/fix-hydration-double-fetch.md
Patch version bump indicating hydration refetch fix.
Documentation
docs/framework/react/guides/ssr.md, docs/framework/react/reference/hydration.md
Updated SSR guide with hydration-aware behavior explanation, staleTime guidance, server memory considerations, and Next.js rewrite caveats; clarified HydrationBoundary prevents unnecessary refetching during hydration.
Type System
packages/query-core/src/types.ts
Added internal _isHydrating?: boolean flag to QueryObserverOptions to mark queries pending hydration.
Core Query Logic
packages/query-core/src/queryObserver.ts
Introduced hydration-aware fetch logic in onSubscribe: resolves refetchOnMount, computes shouldSkipFetchForHydration, and skips fetch if hydrating and data is fresh.
Hydration Context
packages/react-query/src/IsHydratingProvider.ts
New module exporting useIsHydrating hook and IsHydratingProvider for tracking pending hydration queries without triggering re-renders via mutable ref context.
HydrationBoundary Component
packages/react-query/src/HydrationBoundary.tsx
Significant refactor: added hydratingQueriesRef to track pending queries, reworked hydrationQueue logic to distinguish new vs. existing queries, implemented cleanup of hydration flags post-hydration, and wrapped children with IsHydratingProvider to expose pending hydration state.
React Query Hooks
packages/react-query/src/useBaseQuery.ts, packages/react-query/src/useQueries.ts
Integrated useIsHydrating to detect pending hydration and set _isHydrating flag on query options before observer creation.
Public API
packages/react-query/src/index.ts
Exported new public hooks useIsHydrating and IsHydratingProvider.
Test Suite
packages/react-query/src/__tests__/HydrationBoundary.test.tsx
Comprehensive new test coverage (882 lines) validating hydration behavior across multiple refetchOnMount configurations, staleTime scenarios, multi-query interactions, and edge cases to prevent double-fetching.

Sequence Diagram

sequenceDiagram
    participant HB as HydrationBoundary
    participant UBQ as useBaseQuery/<br/>useQueries
    participant QO as QueryObserver
    participant Cache as Query Cache

    HB->>HB: Track dehydrated queries<br/>Mark existing queries in<br/>hydratingQueriesRef
    HB->>HB: Wrap children with<br/>IsHydratingProvider
    HB->>Cache: Hydrate new queries
    
    UBQ->>UBQ: Check useIsHydrating()<br/>for queryHash
    UBQ->>UBQ: Set _isHydrating=true<br/>if pending
    UBQ->>QO: Create observer with<br/>_isHydrating flag
    
    QO->>QO: onSubscribe: Compute<br/>shouldSkipFetchForHydration
    QO->>QO: Check: _isHydrating &&<br/>!refetchOnMount='always' &&<br/>!isStale?
    
    alt Data Fresh & Hydrating
        QO->>QO: Skip fetch, use<br/>existing data
    else Data Stale or Always
        QO->>Cache: Perform refetch
    end
    
    HB->>HB: After hydration,<br/>clean hydratingQueriesRef
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Suggested Reviewers

  • TkDodo
  • manudeli

Poem

🐰 Hydration's dance, no longer twice,
Fresh data flows without the price,
A ref-tracked state, so smooth and light,
Prevents the fetch, keeps servers right!

🚥 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 clearly and accurately summarizes the main fix: preventing unnecessary refetch during hydration in HydrationBoundary.
Description check ✅ Passed The description comprehensively covers changes, root cause, solution, files modified, and has checklists completed with a changeset generated.
Linked Issues check ✅ Passed The PR successfully addresses issue #9610 by preventing unnecessary refetch when hydrating existing queries by tracking pending hydration state and skipping fetch until hydration completes.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the hydration double-fetch issue: core observer logic, HydrationBoundary implementation, new hydration context, documentation updates, and comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

@github-actions github-actions bot added documentation Improvements or additions to documentation package: react-query package: query-core labels Dec 14, 2025
@nx-cloud
Copy link

nx-cloud bot commented Dec 14, 2025

View your CI Pipeline Execution ↗ for commit bb9cced

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 17s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-21 01:09:10 UTC

@sukvvon sukvvon force-pushed the fix/hydration-boundary-double-fetch branch from 86745a3 to 8626d42 Compare December 14, 2025 17:56
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 14, 2025

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@9968

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@9968

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@9968

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@9968

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@9968

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@9968

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@9968

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@9968

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@9968

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@9968

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@9968

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@9968

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@9968

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@9968

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@9968

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@9968

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@9968

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@9968

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@9968

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@9968

commit: bb9cced

@codecov
Copy link

codecov bot commented Dec 14, 2025

Codecov Report

❌ Patch coverage is 92.98246% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.83%. Comparing base (9ff3de7) to head (bb9cced).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #9968      +/-   ##
==========================================
+ Coverage   36.86%   42.83%   +5.96%     
==========================================
  Files         245      173      -72     
  Lines       11102     8286    -2816     
  Branches     2079     1688     -391     
==========================================
- Hits         4093     3549     -544     
+ Misses       6484     4347    -2137     
+ Partials      525      390     -135     
Components Coverage Δ
@tanstack/angular-query-experimental 46.35% <ø> (ø)
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister 43.85% <ø> (ø)
@tanstack/query-broadcast-client-experimental 24.39% <ø> (ø)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core 75.49% <66.66%> (-0.05%) ⬇️
@tanstack/query-devtools 3.38% <ø> (ø)
@tanstack/query-persist-client-core 80.12% <ø> (ø)
@tanstack/query-sync-storage-persister 84.61% <ø> (ø)
@tanstack/query-test-utils ∅ <ø> (∅)
@tanstack/react-query 30.24% <97.91%> (+1.24%) ⬆️
@tanstack/react-query-devtools 9.25% <ø> (ø)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client 100.00% <ø> (ø)
@tanstack/solid-query 53.52% <ø> (ø)
@tanstack/solid-query-devtools 64.17% <ø> (ø)
@tanstack/solid-query-persist-client 100.00% <ø> (ø)
@tanstack/svelte-query ∅ <ø> (∅)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client ∅ <ø> (∅)
@tanstack/vue-query 35.67% <ø> (ø)
@tanstack/vue-query-devtools ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sukvvon sukvvon force-pushed the fix/hydration-boundary-double-fetch branch from cfa5d74 to 695fa28 Compare December 27, 2025 17:38
@sukvvon sukvvon marked this pull request as ready for review December 29, 2025 14:28
@tarasvarshava
Copy link

Thanks a lot for this. I hope it gets merged soon 🤞

@TkDodo TkDodo requested a review from Ephem January 18, 2026 12:41

> Note: Only `queries` can be dehydrated with an `HydrationBoundary`.
> Note: `HydrationBoundary` automatically prevents unnecessary refetching during hydration. Queries being hydrated will not trigger a refetch on mount, unless `refetchOnMount` is explicitly set to `'always'`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for this PR! I've only had time to skim it so far and it will take some time before I can dig in properly, but I wanted to provide some quick feedback here.

We also need to account for the case where there is some time in between fetching on the server, and hydrating on the client. This commonly happens when the markup is cached, in which case the hydration can happen days after the fetch on the server. In this situation, we do want to render with the stale data initially (this is what the SSR pass did and we need to match it), but we also want to immediately refetch the data because it's stale.


// WeakSet to track queries that are pending hydration
// Used to prevent double-fetching when HydrationBoundary defers hydration to useEffect
export const pendingHydrationQueries: WeakSet<Query<any, any, any, any>> =
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we can use a global singleton to keep track of this, what if there are several queryClients? In that case a query might just be about to hydrate into one of these, not all of them.

Annoying as that is, I think we need to use a context for this. Note that there is some prior art with isRestoring.

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
In `@packages/react-query/src/HydrationBoundary.tsx`:
- Around line 94-108: Remove the invalid ESLint disable directives referencing
the non-existent rule "react-hooks/refs" in HydrationBoundary.tsx and
useBaseQuery.ts: delete the inline comment before the hydrate call and the block
comments around the loop that adds to hydratingQueriesRef.current (the comments
around the for...of loop that references dehydratedQuery.queryHash) and any
identical directives in useBaseQuery (around the related refs usage); leave the
hydrate(...) call and the hydratingQueriesRef.current.add(...) logic unchanged,
ensuring no other eslint-disable comments are added.

In `@packages/react-query/src/useBaseQuery.ts`:
- Around line 58-63: Remove the invalid ESLint disable comment above the
hydratingQueriesRef access: delete the line "// eslint-disable-next-line
react-hooks/refs" so the code simply checks
hydratingQueriesRef.current.has(defaultedOptions.queryHash) and sets
defaultedOptions._isHydrating = true; ensure no other eslint-disable for
non-existent rules remain near the hydratingQueriesRef usage.

Comment on lines +94 to +108
if (newQueries.length > 0) {
// It's actually fine to call this with queries/state that already exists
// in the cache, or is older. hydrate() is idempotent for queries.
// eslint-disable-next-line react-hooks/refs
hydrate(client, { queries: newQueries }, optionsRef.current)
}

if (existingQueries.length > 0) {
// Add pending hashes to the mutable ref
/* eslint-disable react-hooks/refs */
for (const dehydratedQuery of existingQueries) {
hydratingQueriesRef.current.add(dehydratedQuery.queryHash)
}
/* eslint-enable react-hooks/refs */
return existingQueries
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find ESLint configuration files
echo "=== Checking for ESLint configuration files ==="
fd -t f -e js -e json -e yml -e yaml "eslint" . | head -20

# Check for .eslintrc variants
ls -la . | grep eslint || echo "No ESLint files in root"

# Check package.json for ESLint config
if [ -f package.json ]; then
  echo "=== Checking package.json for eslintConfig ==="
  jq '.eslintConfig' package.json 2>/dev/null || echo "No eslintConfig in root package.json"
fi

Repository: TanStack/query

Length of output: 1194


🏁 Script executed:

#!/bin/bash

# Look for ESLint configuration in packages directory
echo "=== Checking packages for ESLint config ==="
find packages -maxdepth 2 -name ".eslintrc*" -o -name "package.json" | while read file; do
  if [[ "$file" == *"package.json"* ]]; then
    if grep -q "eslintConfig" "$file" 2>/dev/null; then
      echo "Found eslintConfig in: $file"
    fi
  else
    echo "Found ESLint file: $file"
  fi
done

# Find the actual HydrationBoundary.tsx file
echo -e "\n=== Looking for HydrationBoundary.tsx ==="
find . -name "HydrationBoundary.tsx" -type f

Repository: TanStack/query

Length of output: 193


🏁 Script executed:

#!/bin/bash

# Search for any usage of "react-hooks/refs" in the codebase
echo "=== Searching for react-hooks/refs rule usage ==="
rg "react-hooks/refs" . -n

Repository: TanStack/query

Length of output: 687


🏁 Script executed:

#!/bin/bash

# Check the actual HydrationBoundary.tsx file
if [ -f "packages/react-query/src/HydrationBoundary.tsx" ]; then
  echo "=== Lines 94-108 of HydrationBoundary.tsx ==="
  sed -n '94,108p' packages/react-query/src/HydrationBoundary.tsx
  echo ""
  echo "=== Lines 136-141 of HydrationBoundary.tsx ==="
  sed -n '136,141p' packages/react-query/src/HydrationBoundary.tsx
fi

Repository: TanStack/query

Length of output: 1004


🏁 Script executed:

#!/bin/bash

# Check the eslint-plugin-react-hooks rules
echo "=== Checking for eslint-plugin-react-hooks documentation ==="
# First, let's see if it's installed and what version
if [ -d "node_modules/eslint-plugin-react-hooks" ]; then
  echo "eslint-plugin-react-hooks is installed"
  # Check available rules
  if [ -f "node_modules/eslint-plugin-react-hooks/package.json" ]; then
    echo "Version:"
    jq '.version' node_modules/eslint-plugin-react-hooks/package.json
  fi
else
  echo "eslint-plugin-react-hooks not found in node_modules"
fi

# Search for documentation or rule definitions
rg "rules:" node_modules/eslint-plugin-react-hooks --type json --type js | head -20 2>/dev/null || echo "Could not find rules definition"

Repository: TanStack/query

Length of output: 1355


🌐 Web query:

eslint-plugin-react-hooks rules documentation

💡 Result:

The official documentation for eslint-plugin-react-hooks and its rules is on the React site. Key pages:

  • Plugin overview (recommended rules list and plugin notes). [1]
  • rules-of-hooks (react-hooks/rules-of-hooks): enforces the two Rules of Hooks (only call Hooks at top level; only call Hooks from React functions). [2]
  • exhaustive-deps (react-hooks/exhaustive-deps): validates dependency arrays for useEffect/useMemo/useCallback and config options for custom hooks. [3]

If you want, I can fetch and list every rule and their options/examples from the plugin docs.


🏁 Script executed:

#!/bin/bash

# Get the actual list of rules from eslint-plugin-react-hooks
echo "=== Extracting rules from eslint-plugin-react-hooks ==="
if [ -f "node_modules/eslint-plugin-react-hooks/package.json" ]; then
  jq '.main' node_modules/eslint-plugin-react-hooks/package.json
  # Check the main export
  MAIN_FILE=$(jq -r '.main' node_modules/eslint-plugin-react-hooks/package.json)
  if [ -f "node_modules/eslint-plugin-react-hooks/$MAIN_FILE" ]; then
    echo "=== Checking rules in main export ==="
    grep -A 50 "rules:" "node_modules/eslint-plugin-react-hooks/$MAIN_FILE" | head -70
  fi
fi

Repository: TanStack/query

Length of output: 164


🏁 Script executed:

#!/bin/bash

# Check the main eslint.config.js to see react-hooks configuration
echo "=== Checking root eslint.config.js ==="
cat eslint.config.js

Repository: TanStack/query

Length of output: 2186


🏁 Script executed:

#!/bin/bash

# Check if react-hooks/refs rule causes lint errors
# Look for how ESLint is configured for react-query package
echo "=== Checking react-query eslint.config.js ==="
cat packages/react-query/eslint.config.js

Repository: TanStack/query

Length of output: 936


🏁 Script executed:

#!/bin/bash

# Let's look at the actual rule definitions in the plugin
python3 << 'EOF'
import re
import json

# Read the eslint-plugin-react-hooks main file
with open('node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.js', 'r') as f:
    content = f.read()

# Search for rule names
rule_pattern = r"'(rules-of-hooks|exhaustive-deps|refs)'|'react-hooks/([\w-]+)'"
matches = re.findall(rule_pattern, content)

print("Rules found in eslint-plugin-react-hooks:")
# Also look for the object keys in rules object
rules_section = re.search(r'rules\s*:\s*{([^}]+)}', content)
if rules_section:
    rules_content = rules_section.group(1)
    # Find quoted strings that look like rule names
    rule_names = re.findall(r"'([^']+)':", rules_content)
    unique_rules = sorted(set(rule_names))
    for rule in unique_rules:
        print(f"  - {rule}")
EOF

Repository: TanStack/query

Length of output: 144


Remove invalid ESLint disable directives for non-existent react-hooks/refs rule

The react-hooks/refs rule does not exist in eslint-plugin-react-hooks. Only react-hooks/rules-of-hooks and react-hooks/exhaustive-deps are official rules. These disable directives are invalid and should be removed:

  • Line 97: // eslint-disable-next-line react-hooks/refs
  • Lines 103–107: /* eslint-disable react-hooks/refs */ / /* eslint-enable react-hooks/refs */
  • Lines 136–141: /* eslint-disable react-hooks/refs */ / /* eslint-enable react-hooks/refs */

Also in packages/react-query/src/useBaseQuery.ts:60

🧰 Tools
🪛 ESLint

[error] 97-97: Definition for rule 'react-hooks/refs' was not found.

(react-hooks/refs)


[error] 103-103: Definition for rule 'react-hooks/refs' was not found.

(react-hooks/refs)


[error] 107-107: Definition for rule 'react-hooks/refs' was not found.

(react-hooks/refs)

🤖 Prompt for AI Agents
In `@packages/react-query/src/HydrationBoundary.tsx` around lines 94 - 108, Remove
the invalid ESLint disable directives referencing the non-existent rule
"react-hooks/refs" in HydrationBoundary.tsx and useBaseQuery.ts: delete the
inline comment before the hydrate call and the block comments around the loop
that adds to hydratingQueriesRef.current (the comments around the for...of loop
that references dehydratedQuery.queryHash) and any identical directives in
useBaseQuery (around the related refs usage); leave the hydrate(...) call and
the hydratingQueriesRef.current.add(...) logic unchanged, ensuring no other
eslint-disable comments are added.

Comment on lines +58 to +63

// Check if this query is pending hydration (using mutable ref)
// eslint-disable-next-line react-hooks/refs
if (hydratingQueriesRef.current.has(defaultedOptions.queryHash)) {
defaultedOptions._isHydrating = true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove the invalid ESLint disable comment.

The ESLint directive react-hooks/refs references a non-existent rule (as confirmed by static analysis). Additionally, accessing a ref's .current property outside of hooks like useMemo/useCallback does not violate any React hooks rules, so this comment serves no purpose.

🔧 Suggested fix
   // Check if this query is pending hydration (using mutable ref)
-  // eslint-disable-next-line react-hooks/refs
   if (hydratingQueriesRef.current.has(defaultedOptions.queryHash)) {
     defaultedOptions._isHydrating = true
   }
📝 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
// Check if this query is pending hydration (using mutable ref)
// eslint-disable-next-line react-hooks/refs
if (hydratingQueriesRef.current.has(defaultedOptions.queryHash)) {
defaultedOptions._isHydrating = true
}
// Check if this query is pending hydration (using mutable ref)
if (hydratingQueriesRef.current.has(defaultedOptions.queryHash)) {
defaultedOptions._isHydrating = true
}
🧰 Tools
🪛 ESLint

[error] 60-60: Definition for rule 'react-hooks/refs' was not found.

(react-hooks/refs)

🤖 Prompt for AI Agents
In `@packages/react-query/src/useBaseQuery.ts` around lines 58 - 63, Remove the
invalid ESLint disable comment above the hydratingQueriesRef access: delete the
line "// eslint-disable-next-line react-hooks/refs" so the code simply checks
hydratingQueriesRef.current.has(defaultedOptions.queryHash) and sets
defaultedOptions._isHydrating = true; ensure no other eslint-disable for
non-existent rules remain near the hydratingQueriesRef usage.

@sukvvon sukvvon marked this pull request as draft January 21, 2026 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: query-core package: react-query

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HydrationBoundary double fetching on subsequent visits

3 participants