Skip to content

Fix issue with useQuery polling when skip was initialized with true#13155

Merged
jerelmiller merged 9 commits intomainfrom
jerel/fix-skip-polling
Feb 19, 2026
Merged

Fix issue with useQuery polling when skip was initialized with true#13155
jerelmiller merged 9 commits intomainfrom
jerel/fix-skip-polling

Conversation

@jerelmiller
Copy link
Member

@jerelmiller jerelmiller commented Feb 12, 2026

Fixes #13154

Polling was properly skipped when changing from skip: false to skip: true, but when skip was initialized to true, polling kicked in.

This was due to calling updatePolling in a setTimeout which runs after reobserve is called when first subscribing to ObservableQuery (which properly cancels polling when the fetchPolicy is standby). Now updatePolling will also check for standby and cancel polling if detected.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed useQuery incorrectly initiating polling when skip was set to true on the initial render. Polling now correctly remains inactive until skip is disabled.

@changeset-bot
Copy link

changeset-bot bot commented Feb 12, 2026

🦋 Changeset detected

Latest commit: 6f30ec5

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

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

@jerelmiller jerelmiller force-pushed the jerel/fix-skip-polling branch from 940cb04 to e4aa12f Compare February 12, 2026 17:14
@apollo-librarian
Copy link

apollo-librarian bot commented Feb 12, 2026

✅ Docs preview has no changes

The preview was not built because there were no changes.

Build ID: 46b862979f674ba00b37e40e
Build Logs: View logs

@jerelmiller jerelmiller requested a review from phryneas February 12, 2026 17:15
@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 12, 2026

npm i https://pkg.pr.new/apollographql/apollo-client/@apollo/client@13155

commit: 816911d

});

// https://github.com/apollographql/apollo-client/issues/13154
it("doesn't poll when initially skipped", async () => {

Choose a reason for hiding this comment

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

nit: it("does not poll when initially skipped")

Copy link
Member Author

Choose a reason for hiding this comment

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

@Hardanish-Singh I'm fine with it the way it is. The contraction is perfectly fine.

In the future, I'd appreciate if you didn't add these kinds of review comments. They are just noise.

I'm happy to answer specific questions or concerns you may have if you're looking at a PR, but please avoid +1 or nit comments like this. Thanks.

!pollInterval ||
!this.hasObservers() ||
fetchPolicy === "cache-only" ||
fetchPolicy === "standby"
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to add a similar check inside of maybeFetch, too?
Currently all code paths changing any of those seem to be covered, but it seems like it could easily happen that some code path might run out of sync again.

Copy link
Member Author

Choose a reason for hiding this comment

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

info.interval = pollInterval;

const maybeFetch = () => {
if (this.options.fetchPolicy === "standby") {
Copy link
Member

Choose a reason for hiding this comment

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

Actually... do we want to repeat all those other checks here, too? 😅

Copy link
Member Author

Choose a reason for hiding this comment

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

extracted to a helper 🙂 4e167ba

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd42142 and 7a72816.

📒 Files selected for processing (3)
  • .changeset/chilly-games-punch.md
  • src/core/ObservableQuery.ts
  • src/react/hooks/__tests__/useQuery.test.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/react/hooks/__tests__/useQuery.test.tsx (3)
src/core/ApolloClient.ts (2)
  • query (982-1036)
  • ApolloClient (700-1685)
src/link/index.ts (2)
  • ApolloLink (8-8)
  • RequestHandler (16-16)
src/react/hooks/useQuery.ts (1)
  • useQuery (380-399)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Are the types wrong
  • GitHub Check: Api-Extractor
  • GitHub Check: Pull Request Prerelease
  • GitHub Check: Docs Deploy Preview
  • GitHub Check: Compare Build Output
  • GitHub Check: Generate Documentation Model
  • GitHub Check: Pull Request Prerelease
  • GitHub Check: Build and Test
🔇 Additional comments (4)
.changeset/chilly-games-punch.md (1)

1-5: LGTM!

The changeset accurately documents the bug fix with an appropriate patch level for a defect correction.

src/core/ObservableQuery.ts (2)

1426-1439: LGTM!

The shouldCancelPolling helper correctly centralizes the polling cancellation logic and adds the crucial standby check that prevents polling from restarting after reobserve has already canceled it. Re-reading fetchPolicy and pollInterval from this.options inside the helper (rather than using the outer destructured values) is the right approach for the deferred maybeFetch call where options may have changed.


1465-1470: LGTM!

This is the key fix for the reported issue. By checking shouldCancelPolling() at the start of maybeFetch, the deferred polling callback now correctly detects when options have changed (e.g., fetchPolicy became standby due to skip: true) and cancels polling before executing. The comment clearly documents the defensive purpose of this check.

src/react/hooks/__tests__/useQuery.test.tsx (1)

2360-2405: Nice regression coverage for initial skip polling.
The test directly asserts both “no rerender” and “no link calls” under skip: true + pollInterval, which matches the reported failure mode.


📝 Walkthrough

Walkthrough

A patch fix is introduced to resolve an issue where useQuery continues polling with pollInterval even when skip is initially true. The fix adds a shouldCancelPolling helper function to ObservableQuery that determines when polling should be canceled, preventing unwanted polling during initialization and subsequent polling cycles.

Changes

Cohort / File(s) Summary
Changeset Documentation
.changeset/chilly-games-punch.md
Marks a patch release documenting the fix for polling behavior when skip is initially true.
Core Observable Query Logic
src/core/ObservableQuery.ts
Introduces a centralized shouldCancelPolling helper function that encapsulates polling cancellation conditions (no pollInterval, no observers, cache-only or standby fetch policies). The helper is applied during initial polling guard and pre-checked in the polling path to prevent stale polling when options change.
Test Coverage
src/react/hooks/__tests__/useQuery.test.tsx
Adds a new test case "doesn't poll when initially skipped" that verifies the query does not poll or make network requests when skip: true and pollInterval are both set on initial render.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly describes the main fix: preventing polling when useQuery is initialized with skip set to true, which aligns perfectly with the changeset and objectives.
Linked Issues check ✅ Passed The PR addresses the core requirement from issue #13154: preventing polling from starting when useQuery has skip: true, by adding shouldCancelPolling checks in ObservableQuery and including a test to verify the fix.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the skip/polling bug: the helper function, polling checks, test case, and changeset documentation are all within scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ 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 jerel/fix-skip-polling

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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

Copy link
Member

@phryneas phryneas left a comment

Choose a reason for hiding this comment

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

one last suggestion to shave a few yaks/bytes, generally approved

@github-actions github-actions bot added the auto-cleanup 🤖 label Feb 19, 2026
jerelmiller and others added 2 commits February 19, 2026 09:47
Co-authored-by: Lenz Weber-Tronic <lorenz.weber-tronic@apollographql.com>
@jerelmiller jerelmiller merged commit 3ba1583 into main Feb 19, 2026
33 checks passed
@jerelmiller jerelmiller deleted the jerel/fix-skip-polling branch February 19, 2026 17:01
@github-actions github-actions bot mentioned this pull request Feb 19, 2026
jerelmiller pushed a commit that referenced this pull request Feb 19, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @apollo/client@4.1.5

### Patch Changes

- [#13155](#13155)
[`3ba1583`](3ba1583)
Thanks [@jerelmiller](https://github.com/jerelmiller)! - Fix an issue
where `useQuery` would poll with `pollInterval` when `skip` was
initialized to `true`.

- [#13135](#13135)
[`fd42142`](fd42142)
Thanks [@jerelmiller](https://github.com/jerelmiller)! - Fix issue where
`client.query` would apply options from `defaultOptions.watchQuery`.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skip-option ignored when pollInterval is set on useQuery

3 participants

Comments