From 3d64dc60f1a4b4b416643035f0c9827ab0d8960c Mon Sep 17 00:00:00 2001 From: xxziiko Date: Thu, 8 May 2025 20:17:25 +0900 Subject: [PATCH 1/6] docs(react-query): ensure suspense example fallback renders correctly (#9119) The previous suspense example incorrectly rendered null instead of the fallback UI. This change moves the null check outside the Suspense component to ensure the fallback is displayed as expected. Fixes #9019 --- examples/react/suspense/src/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/react/suspense/src/index.tsx b/examples/react/suspense/src/index.tsx index 814718dd783..2402fa9393a 100755 --- a/examples/react/suspense/src/index.tsx +++ b/examples/react/suspense/src/index.tsx @@ -70,18 +70,18 @@ function Example() { )} onReset={reset} > - Loading projects...}> - {showProjects ? ( - activeProject ? ( + {showProjects ? ( + Loading projects...}> + {activeProject ? ( ) : ( - ) - ) : null} - + )} + + ) : null} )} From 32414aab2f953e367da9ffe8b93223a591063b8b Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Thu, 8 May 2025 10:19:18 -0600 Subject: [PATCH 2/6] Update README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 0b8f949f6f3..d728747a520 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,16 @@ Still on **React Query v4**? No problem! Check out the v4 docs here: https://tan - [React Suspense](https://react.dev/reference/react/Suspense) + Fetch-As-You-Render Query Prefetching - Dedicated Devtools +## Partners + + + Speakeasy Logo + + ## Contributing View the contributing guidelines [here](/CONTRIBUTING.md) @@ -52,3 +62,4 @@ View the contributing guidelines [here](/CONTRIBUTING.md) ### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/) +[ From 37d8eb6ff968c44e0eb8564536a85b0af918820b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:20:30 +0000 Subject: [PATCH 3/6] ci: apply automated fixes --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d728747a520..bd682ca53a0 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,5 @@ View the contributing guidelines [here](/CONTRIBUTING.md) ### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/) + [ From 6ee1e666fe267af8c77357648d5c8b9ab454dd17 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Thu, 8 May 2025 10:22:43 -0600 Subject: [PATCH 4/6] Update README.md --- README.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bd682ca53a0..5c50ea320d2 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,21 @@ Still on **React Query v4**? No problem! Check out the v4 docs here: https://tan ## Partners - Speakeasy Logo + + + + + Speakeasy Logo + ## Contributing @@ -62,5 +72,4 @@ View the contributing guidelines [here](/CONTRIBUTING.md) ### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/) - [ From 8f092f9e4acf9f6dd8407bb059a4191dd7096f67 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:23:54 +0000 Subject: [PATCH 5/6] ci: apply automated fixes --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5c50ea320d2..68c42c5c802 100644 --- a/README.md +++ b/README.md @@ -72,4 +72,5 @@ View the contributing guidelines [here](/CONTRIBUTING.md) ### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/) + [ From 57251a4e240232b9dcb2627a9ecd1fe1f2b3184e Mon Sep 17 00:00:00 2001 From: Arnoud <6420061+arnoud-dv@users.noreply.github.com> Date: Thu, 8 May 2025 21:52:29 +0200 Subject: [PATCH 6/6] feature(angular-query): support providing QueryClient via an InjectionToken (#9128) This is useful for example in thin app shell applications where feature teams provide their dependencies on lazy loaded route providers while still allowing to easily share a QueryClient. This way the main bundle for the app shell does not include TanStack Query. --- .../__tests__/provide-query-client.test.ts | 41 +++++++++++++++++++ .../__tests__/provide-tanstack-query.test.ts | 41 +++++++++++++++++++ .../src/providers.ts | 35 +++++++++++----- 3 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts create mode 100644 packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts diff --git a/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts b/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts new file mode 100644 index 00000000000..5758a17457f --- /dev/null +++ b/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts @@ -0,0 +1,41 @@ +import { TestBed } from '@angular/core/testing' +import { describe, expect, test } from 'vitest' +import { + InjectionToken, + provideExperimentalZonelessChangeDetection, +} from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { provideQueryClient } from '../providers' + +describe('provideQueryClient', () => { + test('should provide a QueryClient instance directly', () => { + const queryClient = new QueryClient() + + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), + provideQueryClient(queryClient), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) + + test('should provide a QueryClient instance using an InjectionToken', () => { + const queryClient = new QueryClient() + const CUSTOM_QUERY_CLIENT = new InjectionToken('', { + factory: () => queryClient, + }) + + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), + provideQueryClient(CUSTOM_QUERY_CLIENT), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts b/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts new file mode 100644 index 00000000000..c35eb406a5c --- /dev/null +++ b/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts @@ -0,0 +1,41 @@ +import { TestBed } from '@angular/core/testing' +import { describe, expect, test } from 'vitest' +import { + InjectionToken, + provideExperimentalZonelessChangeDetection, +} from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { provideTanStackQuery } from '../providers' + +describe('provideTanStackQuery', () => { + test('should provide a QueryClient instance directly', () => { + const queryClient = new QueryClient() + + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), + provideTanStackQuery(queryClient), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) + + test('should provide a QueryClient instance using an InjectionToken', () => { + const queryClient = new QueryClient() + const CUSTOM_QUERY_CLIENT = new InjectionToken('', { + factory: () => queryClient, + }) + + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), + provideTanStackQuery(CUSTOM_QUERY_CLIENT), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) +}) diff --git a/packages/angular-query-experimental/src/providers.ts b/packages/angular-query-experimental/src/providers.ts index 98ea2e04ed8..0a7f784f4c0 100644 --- a/packages/angular-query-experimental/src/providers.ts +++ b/packages/angular-query-experimental/src/providers.ts @@ -1,6 +1,7 @@ import { DestroyRef, ENVIRONMENT_INITIALIZER, + InjectionToken, PLATFORM_ID, computed, effect, @@ -25,10 +26,19 @@ import type { * for the entire application. You can use `provideQueryClient` to provide a * different `QueryClient` instance for a part of the application. * @param queryClient - the `QueryClient` instance to provide. - * @public + * @returns a provider object that can be used to provide the `QueryClient` instance. */ -export function provideQueryClient(queryClient: QueryClient) { - return { provide: QueryClient, useValue: queryClient } +export function provideQueryClient( + queryClient: QueryClient | InjectionToken, +): Provider { + return { + provide: QueryClient, + useFactory: () => { + return queryClient instanceof InjectionToken + ? inject(queryClient) + : queryClient + }, + } } /** @@ -83,15 +93,14 @@ export function provideQueryClient(queryClient: QueryClient) { * } * ) * ``` - * @param queryClient - A `QueryClient` instance. + * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. * @param features - Optional features to configure additional Query functionality. * @returns A set of providers to set up TanStack Query. - * @public * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start * @see withDevtools */ export function provideTanStackQuery( - queryClient: QueryClient, + queryClient: QueryClient | InjectionToken, ...features: Array ): EnvironmentProviders { return makeEnvironmentProviders([ @@ -100,10 +109,16 @@ export function provideTanStackQuery( // Do not use provideEnvironmentInitializer while Angular < v19 is supported provide: ENVIRONMENT_INITIALIZER, multi: true, - useValue: () => { - queryClient.mount() - // Unmount the query client on application destroy - inject(DestroyRef).onDestroy(() => queryClient.unmount()) + useFactory: () => { + const client = + queryClient instanceof InjectionToken + ? inject(queryClient) + : queryClient + return () => { + client.mount() + // Unmount the query client on application destroy + inject(DestroyRef).onDestroy(() => client.unmount()) + } }, }, features.map((feature) => feature.ɵproviders),