Repository navigation
Conversation
3 of 5 tasks
🚀 Changeset Version Preview1 package(s) bumped directly, 23 bumped as dependents. 🟩 Patch bumps
|
3 of 5 tasks
… 'retry' options A query hydrated while pending resumes the dehydrated promise through a retryer created at hydration time, before any observer has set the query's options. Its retries used the 'retry' and 'retryDelay' the query had then, so an observer's 'retry: false' or 'retryDelay' was ignored. Read 'retry' and 'retryDelay' from the query's options at the time of each failure for fetches that resume an 'initialPromise'. Other fetches keep the options they started with. Co-authored-by: alexander <alexander@n1s.se>
… with 'using' Co-authored-by: alexander <alexander@n1s.se>
… with 'using' Adds a 'subscribe' helper to @tanstack/query-test-utils that returns a Disposable, and a test for it and for 'clearOnDispose'. Co-authored-by: alexander <alexander@n1s.se>
Co-authored-by: alexander <alexander@n1s.se>
…ions Co-authored-by: alexander <alexander@n1s.se>
…de hydration Client defaults and setQueryDefaults no longer count as set, so they don't override hydrate.queries.retry. Co-authored-by: alexander <alexander@n1s.se>
…the observer's retry Co-authored-by: alexander <alexander@n1s.se>
cursor
Bot
force-pushed
the
cursor/hydrated-rejection-retry-271e
branch
from
November 2, 2026 19:56
3ff29ca to
9e4a941
Compare
Owner
Author
|
Moved to TanStack#12511. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 Changes
When
dehydrateincludes a pending query,hydrateresumes its promise on the client. That fetch starts before any observer exists, so its retryer tookretryandretryDelayfrom the options the query had at hydration. IfuseQuerymounted withretry: false, or a differentretryDelay, before the server promise rejected, the hydration options still decided whether and when the query retried.Now, for fetches that resume a hydrated promise (
initialPromise), the retryer reads both options at each failure:retryorretryDelayitself, that value wins.master. Client defaults (defaultOptions.queries) andsetQueryDefaultsdon't count as set by the observer, so they don't overridehydrate.queriesvalues. For example, a client withqueries.retry: 2that hydrates withhydrate.queries.retry: 0still fails at once.useQuerymerges client defaults into its options before it creates the observer, so the observer can't tell which values the caller set.queryClient.defaultQueryOptionstherefore records theretryandretryDelayit was called with, in a module-levelWeakMapkeyed by the options object it returns. Options objects gain no new properties, and nothing else reads the map.Infinite queries get the same fix.
infiniteQueryBehaviorused to build every retry of a hydrated infinite query from the options the fetch started with, which have noqueryFn, so each retry replayed the rejected promise. When the fetch resumes a hydrated promise, a retry now readsqueryFn,initialPageParam,getNextPageParamand the other page options from the query's current options. With an observer mounted, it runs the observer'squeryFnfrom the first page, as plain queries already did. With no observer, it replays the rejection as before. Whether it retries at all follows the rules above.A fetch that joins a running fetch gets that fetch's shared promise (TanStack#12489). When the running fetch resumes a hydrated promise, the shared promise resolves with the data of the retry the observer configured.
Every other fetch keeps the options it started with, and a new test in
query.test.tsxchecks that.Out of scope:
networkModestill comes from the options the fetch started with, as onmaster.New tests in
hydration.test.tsx:retryandretryDelay, and runs the observer'squeryFnretry: falseon an observer stops retriessetQueryDefaultsqueryFnfrom the first pageThe new tests clean up with
using:using _timers = fakeTimers()switches timers,using queryClient = clearOnDispose(new QueryClient())clears each client, andusing _subscription = subscribe(observer, noop)unsubscribes each observer. This PR adds all three helpers, with tests, to@tanstack/query-test-utils. The existing hooks in these files stay as they were.This PR doesn't depend on #2, and they share no code. #2 adds the same three helpers byte for byte, so whichever merges second only has to merge the export list in
query-test-utils/src/index.ts.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request. (Ran oxlint, knip,test:typesacross all TS versions and vitest for query-core, query-test-utils and react-query, plus the docs link check.)🚀 Release Impact