diff --git a/.changeset/olive-pugs-shave.md b/.changeset/olive-pugs-shave.md new file mode 100644 index 00000000000..3ead4f59c3d --- /dev/null +++ b/.changeset/olive-pugs-shave.md @@ -0,0 +1,5 @@ +--- +'@tanstack/router-ssr-query-core': patch +--- + +skip hydration when the query stream closes diff --git a/packages/router-ssr-query-core/src/index.ts b/packages/router-ssr-query-core/src/index.ts index 685653dea0c..0425728c3f7 100644 --- a/packages/router-ssr-query-core/src/index.ts +++ b/packages/router-ssr-query-core/src/index.ts @@ -195,10 +195,10 @@ export function setupCoreRouterSsrQueryIntegration({ reader .read() .then(async function handle({ done, value }) { - queryHydrate(queryClient, value, hydrateOptions) if (done) { return } + queryHydrate(queryClient, value, hydrateOptions) const result = await reader.read() return handle(result) }) diff --git a/packages/router-ssr-query-core/tests/stream-close.test.ts b/packages/router-ssr-query-core/tests/stream-close.test.ts new file mode 100644 index 00000000000..3f757fe84d6 --- /dev/null +++ b/packages/router-ssr-query-core/tests/stream-close.test.ts @@ -0,0 +1,38 @@ +import { QueryClient, hydrate } from '@tanstack/query-core' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { setupCoreRouterSsrQueryIntegration } from '../src' + +vi.mock('@tanstack/query-core', async (importOriginal) => { + const actual = await importOriginal() + return { ...actual, hydrate: vi.fn(actual.hydrate) } +}) + +describe('setupCoreRouterSsrQueryIntegration', () => { + beforeEach(() => { + vi.mocked(hydrate).mockClear() + }) + + it('does not hydrate once the query stream is closed', async () => { + const queryClient = new QueryClient() + const router = { isServer: false, options: {} } as { + isServer: boolean + options: { hydrate?: (dehydrated: any) => unknown | Promise } + } + + setupCoreRouterSsrQueryIntegration({ router: router as any, queryClient }) + + const stream = new ReadableStream({ + start(controller) { + controller.enqueue({ mutations: [], queries: [] }) + controller.close() + }, + }) + + await router.options.hydrate?.({ queryStream: stream }) + await vi.waitFor(() => expect(hydrate).toHaveBeenCalled()) + + expect( + vi.mocked(hydrate).mock.calls.some(([, state]) => state === undefined), + ).toBe(false) + }) +})