Repository navigation
Conversation
…bles for 'using' in tests Co-authored-by: alexander <alexander@n1s.se>
…eWaterfall' Co-authored-by: alexander <alexander@n1s.se>
Co-authored-by: alexander <alexander@n1s.se>
Co-authored-by: alexander <alexander@n1s.se>
…' with a plain 'experimental_waterfallHandle' whose reader starts the query Co-authored-by: alexander <alexander@n1s.se>
Adds an 'unmountOnDispose' helper to @tanstack/query-test-utils, so a render declared after its client unmounts before the client is cleared, and splits the helper tests into one file per helper. Co-authored-by: alexander <alexander@n1s.se>
… copy Co-authored-by: alexander <alexander@n1s.se>
Also keep optional elements in a handle's key type, and test streaming a pending query, infinite fetchHandle and server clients. The guide now covers promise transports and data that goes out twice. Co-authored-by: alexander <alexander@n1s.se>
Keep experimental_QueryHandle, experimental_QueryHandleWithData, experimental_QueryHandleFactory and experimental_FromHandleOptions. The guide and tests now cover a handle's data seeding the cache again after clear(), removeQueries or resetQueries, as any initialData does. Co-authored-by: alexander <alexander@n1s.se>
Every handle is now a plain { queryKey, input }. experimental_ensureHandle
and experimental_fetchHandle still wait for the data, but return the same
handle as experimental_prefetchHandle, and experimental_fromHandle adds no
initialData. Readers that need defined data use useSuspenseQuery.
Co-authored-by: alexander <alexander@n1s.se>
…Handle Covers a read-site select spread over the options, a select inside the factory, and a read-site select over a factory that already selects, for useQuery, useSuspenseQuery and the infinite hooks. Co-authored-by: alexander <alexander@n1s.se>
It gives the data a reader of a factory's query gets, the same type as useSuspenseQuery's data, so a component can type a prop that takes it. Co-authored-by: alexander <alexander@n1s.se>
…r queries in the devtools Co-authored-by: alexander <alexander@n1s.se>
…nfo tests with 'using' Adds the 'subscribe' helper to @tanstack/query-test-utils, as in the hydrated rejection retry PR, and uses query-test-utils in query-devtools instead of a local 'clearOnDispose'. Console spies are held with 'using' too. Co-authored-by: alexander <alexander@n1s.se>
… copy Co-authored-by: alexander <alexander@n1s.se>
…n less Track waterfall handles in a WeakSet, so a Server Component can pass them on. dehydrate now warns once per query, only on the server, and not for queries an earlier dehydrate sent. A start on fresh data notifies the cache, so the devtools show it, and hydrate only restores start info in development. Co-authored-by: alexander <alexander@n1s.se>
Production builds add no cache listener and wrap no queryFn. Co-authored-by: alexander <alexander@n1s.se>
🦋 Changeset detectedLatest commit: f639acc The changes in this PR will be included in the next version bump. This PR includes changesets to release 24 packages
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 |
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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. CodeRabbit Verify
|
This was referenced Nov 3, 2026
This branch has not been deployed
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.
Note
We made this PR with AI help and haven't yet done the two steps in TanStack's AI Contribution Policy. We still need to check that we understand all the code, and to rewrite this description in our own words.
Builds on #12512. Review only the commits after b6bc296.
This is a separate PR to keep #12512's core changes small.
🎯 Changes
Core records start info only in development. In a production build, the handle functions return the factory's options untouched, add no cache listener and wrap no
queryFn, andexperimental_getQueryStartInforeturnsundefined.query-core
Symbol.for('@tanstack/query-core/experimental_start')key on theQueryobject, because the devtools bundle their own copy of query-core and wouldn't see a module-level map.experimental_getQueryStartInfo(query)reads it, andexperimental_QueryStartInfotypes it. A start on fresh data fetches nothing, so recording it emits anobserverResultsUpdatedcache event, which tells the devtools to read the new record.experimental_waterfallHandlestarts nothing, so in development core keeps its handles in a module-levelWeakSetinstead. The handles stay plain{ queryKey, input }objects with no symbol properties, so a Server Component can pass them to a Client Component. For a handle in the set,experimental_fromHandlewraps the options'queryFn, so the query records the reader's first fetch with the verbwaterfallHandle. Refetches don't overwrite that record, and when the switch form returns the loader's own handle, the loader's record stays.dehydrateincludes the start info asexperimental_start, andhydraterestores it withobserved: false, so a hydrated query keeps the server's record.dehydrateon the server warns once when it leaves out a pending query thatexperimental_prefetchHandle,experimental_ensureHandleorexperimental_fetchHandlestarted there, since the browser would fetch it again. Queries an earlierdehydratecall sent don't count, so the guide's nested-dehydration pattern andReactQueryStreamedHydrationdon't warn, and neither does a browserdehydrateof a hydrated query. The warning belongs here rather than in feat(query-core, react-query): add experimental query handles #12512 because it needs the start info to know which function started the query, and where.query-devtools
waterfallbadge, also in the row's aria-label, on queries that a reader of anexperimental_waterfallHandlehandle first fetched.experimental_getQueryStartInfofrom their own copy of query-core, which finds the same registered symbol. The build only bundles that one function.Docs
The query handles guide gains a sentence on the dev warning, a mention of the waterfall badge, and a Devtools section, which says that production builds record nothing, so the devtools show none of it there.
Tests
queryStartInfo.test.tsxcovers recording andobserved, the waterfall reader's first fetch, waterfall handles with no symbol properties, a switched-back loader handle, the cache event for a start on fresh data, start info thatresetQuerieskeeps, queries that other APIs start, the record moving from server to client, and when the warning shows: once per query, not for queries an earlierdehydratesent, and not when the browser dehydrates a hydrated query. Two tests stubNODE_ENVtoproductionand check that nothing is recorded, thequeryFnisn't wrapped, and the cache has no listener. TheDehydratedQuerykey-set type test covers the new field.waterfallHandletest also checks that the query records a suspense reader's fetch and marks it as read.using:subscribe(observer, noop)unsubscribes observers,unmountOnDispose(...)unmounts renders, theconsole.warnspies dispose themselves, and aproductionEnvironment()helper restoresNODE_ENV. query-devtools now uses@tanstack/query-test-utilsas a dev dependency instead of its ownclearOnDispose.Screenshots
These come from a small React app running in development mode. Its loader awaits the viewer with
experimental_ensureHandle, and prefetches page 1 of the posts and the stats withexperimental_prefetchHandle. The page reads the viewer and the posts withexperimental_fromHandle, and never reads the stats. "Next page" switches the posts handle withexperimental_waterfallHandle.Before the switch, Query Details shows that
prefetchHandlestarted page 1:The loader prefetched the stats, but no component read them:
After the switch, page 2 has the
waterfallbadge, and Query Details shows thatwaterfallHandlestarted it:The whole flow:
✅ 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-devtools, react-query and query-test-utils, plus the docs link check.)🚀 Release Impact