From fd4c002536bc3ec50b4fbf74f4c63a5ea6a5242a Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Mar 2024 10:01:52 -0700 Subject: [PATCH 1/8] Add tests to useBackgroundQuery to demonstrate intended behavior --- .../__tests__/useBackgroundQuery.test.tsx | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx index ac7477d51f7..f9f934cb392 100644 --- a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx +++ b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx @@ -446,6 +446,77 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use await expect(Profiler).not.toRerender({ timeout: 50 }); }); +it("disposes of the queryRef when unmounting before it is used by useReadQuery", async () => { + const { query, mocks } = setupSimpleCase(); + const client = new ApolloClient({ + link: new MockLink(mocks), + cache: new InMemoryCache(), + }); + + const Profiler = createDefaultProfiler(); + + function App() { + useTrackRenders(); + useBackgroundQuery(query); + + return null; + } + + const { unmount } = renderWithClient(, { client, wrapper: Profiler }); + + expect(client.getObservableQueries().size).toBe(1); + expect(client).toHaveSuspenseCacheEntryUsing(query); + + { + const { renderedComponents } = await Profiler.takeRender(); + + expect(renderedComponents).toStrictEqual([App]); + } + + unmount(); + await wait(0); + + expect(client.getObservableQueries().size).toBe(0); + expect(client).not.toHaveSuspenseCacheEntryUsing(query); +}); + +it("does not prematurely dispose of the queryRef when using strict mode", async () => { + const { query, mocks } = setupSimpleCase(); + const client = new ApolloClient({ + link: new MockLink(mocks), + cache: new InMemoryCache(), + }); + + const Profiler = createDefaultProfiler(); + + function App() { + useTrackRenders(); + useBackgroundQuery(query); + + return null; + } + + renderWithClient(, { + client, + wrapper: ({ children }) => ( + + {children} + + ), + }); + + { + const { renderedComponents } = await Profiler.takeRender(); + + expect(renderedComponents).toStrictEqual([App]); + } + + await wait(10); + + expect(client.getObservableQueries().size).toBe(1); + expect(client).toHaveSuspenseCacheEntryUsing(query); +}); + it("allows the client to be overridden", async () => { const { query } = setupSimpleCase(); From d49341d478ec562be90c62c93ff344519d656075 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Mar 2024 10:13:12 -0700 Subject: [PATCH 2/8] Add failing test for changing variables without consuming queryRef --- .../__tests__/useBackgroundQuery.test.tsx | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx index f9f934cb392..54ad243d5ba 100644 --- a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx +++ b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx @@ -480,6 +480,51 @@ it("disposes of the queryRef when unmounting before it is used by useReadQuery", expect(client).not.toHaveSuspenseCacheEntryUsing(query); }); +it("disposes of old queryRefs when changing variables before the queryRef is used by useReadQuery", async () => { + const { query, mocks } = setupVariablesCase(); + const client = new ApolloClient({ + link: new MockLink(mocks), + cache: new InMemoryCache(), + }); + + const Profiler = createDefaultProfiler(); + + function App({ id }: { id: string }) { + useTrackRenders(); + useBackgroundQuery(query, { variables: { id } }); + + return null; + } + + const { rerender } = renderWithClient(, { + client, + wrapper: Profiler, + }); + + expect(client.getObservableQueries().size).toBe(1); + expect(client).toHaveSuspenseCacheEntryUsing(query, { + variables: { id: "1" }, + }); + + { + const { renderedComponents } = await Profiler.takeRender(); + + expect(renderedComponents).toStrictEqual([App]); + } + + rerender(); + + await wait(0); + + expect(client.getObservableQueries().size).toBe(1); + expect(client).toHaveSuspenseCacheEntryUsing(query, { + variables: { id: "2" }, + }); + expect(client).not.toHaveSuspenseCacheEntryUsing(query, { + variables: { id: "1" }, + }); +}); + it("does not prematurely dispose of the queryRef when using strict mode", async () => { const { query, mocks } = setupSimpleCase(); const client = new ApolloClient({ From ffd72119fbc4d9afc04a84fddbb5eddf79f437d4 Mon Sep 17 00:00:00 2001 From: PiR1 Date: Mon, 18 Mar 2024 19:39:07 +0100 Subject: [PATCH 3/8] fix(useBackgroundQuery): track uses to dispose ref after unmount --- .changeset/fast-roses-kick.md | 5 +++ src/react/hooks/useBackgroundQuery.ts | 14 ++++-- src/react/internal/cache/QueryReference.ts | 51 +++++++++++++++------- src/react/internal/cache/SuspenseCache.ts | 19 +++++--- 4 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 .changeset/fast-roses-kick.md diff --git a/.changeset/fast-roses-kick.md b/.changeset/fast-roses-kick.md new file mode 100644 index 00000000000..60c9e5c74bb --- /dev/null +++ b/.changeset/fast-roses-kick.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +useBackgroundQuery, handle ref disposal if unmount before used diff --git a/src/react/hooks/useBackgroundQuery.ts b/src/react/hooks/useBackgroundQuery.ts index 8d83c50fc00..6f0e2df4108 100644 --- a/src/react/hooks/useBackgroundQuery.ts +++ b/src/react/hooks/useBackgroundQuery.ts @@ -15,7 +15,7 @@ import { } from "../internal/index.js"; import type { CacheKey, QueryReference } from "../internal/index.js"; import type { BackgroundQueryHookOptions, NoInfer } from "../types/types.js"; -import { __use, wrapHook } from "./internal/index.js"; +import { wrapHook } from "./internal/index.js"; import { useWatchQueryOptions } from "./useSuspenseQuery.js"; import type { FetchMoreFunction, RefetchFunction } from "./useSuspenseQuery.js"; import { canonicalStringify } from "../../cache/index.js"; @@ -224,8 +224,10 @@ function _useBackgroundQuery< ...([] as any[]).concat(queryKey), ]; - const queryRef = suspenseCache.getQueryRef(cacheKey, () => - client.watchQuery(watchQueryOptions as WatchQueryOptions) + const queryRef = suspenseCache.getQueryRef( + cacheKey, + () => client.watchQuery(watchQueryOptions as WatchQueryOptions), + true ); const [wrappedQueryRef, setWrappedQueryRef] = React.useState( @@ -261,6 +263,12 @@ function _useBackgroundQuery< [queryRef] ); + React.useEffect(() => { + return () => { + queryRef.disposeOnUnmount(); + }; + }, [queryRef]); + return [ didFetchResult.current ? wrappedQueryRef : void 0, { fetchMore, refetch }, diff --git a/src/react/internal/cache/QueryReference.ts b/src/react/internal/cache/QueryReference.ts index 50865abe2d4..ac0a639ac85 100644 --- a/src/react/internal/cache/QueryReference.ts +++ b/src/react/internal/cache/QueryReference.ts @@ -154,20 +154,25 @@ export class InternalQueryReference { private subscription!: ObservableSubscription; private listeners = new Set>(); private autoDisposeTimeoutId?: NodeJS.Timeout; + private readonly autoDisposeTimeoutMs?: number; private resolve: ((result: ApolloQueryResult) => void) | undefined; private reject: ((error: unknown) => void) | undefined; private references = 0; + private nbOfUse = 0; constructor( observable: ObservableQuery, - options: InternalQueryReferenceOptions + options: InternalQueryReferenceOptions, + trackUses: boolean = false ) { this.handleNext = this.handleNext.bind(this); this.handleError = this.handleError.bind(this); this.dispose = this.dispose.bind(this); this.observable = observable; + this.autoDisposeTimeoutMs = options.autoDisposeTimeoutMs ?? 30_000; + this.nbOfUse = trackUses ? 1 : 0; if (options.onDispose) { this.onDispose = options.onDispose; @@ -176,23 +181,13 @@ export class InternalQueryReference { this.setResult(); this.subscribeToQuery(); - // Start a timer that will automatically dispose of the query if the - // suspended resource does not use this queryRef in the given time. This - // helps prevent memory leaks when a component has unmounted before the - // query has finished loading. - const startDisposeTimer = () => { - if (!this.references) { - this.autoDisposeTimeoutId = setTimeout( - this.dispose, - options.autoDisposeTimeoutMs ?? 30_000 - ); - } - }; - // We wait until the request has settled to ensure we don't dispose of the // query ref before the request finishes, otherwise we would leave the // promise in a pending state rendering the suspense boundary indefinitely. - this.promise.then(startDisposeTimer, startDisposeTimer); + this.promise.then( + this.startDisposeTimer.bind(this), + this.startDisposeTimer.bind(this) + ); } get disposed() { @@ -203,6 +198,19 @@ export class InternalQueryReference { return this.observable.options; } + // Start a timer that will automatically dispose of the query if the + // suspended resource does not use this queryRef in the given time. This + // helps prevent memory leaks when a component has unmounted before the + // query has finished loading. + startDisposeTimer() { + if (!this.references) { + this.autoDisposeTimeoutId = setTimeout( + this.dispose, + this.autoDisposeTimeoutMs ?? 30_000 + ); + } + } + reinitialize() { const { observable } = this; @@ -251,6 +259,19 @@ export class InternalQueryReference { }; } + newUsage() { + this.nbOfUse++; + clearTimeout(this.autoDisposeTimeoutId); + this.startDisposeTimer(); + } + + disposeOnUnmount() { + this.nbOfUse--; + if (!this.nbOfUse && !this.references) { + this.dispose(); + } + } + didChangeOptions(watchQueryOptions: ObservedOptions) { return OBSERVED_CHANGED_OPTIONS.some( (option) => diff --git a/src/react/internal/cache/SuspenseCache.ts b/src/react/internal/cache/SuspenseCache.ts index d66eb905a5a..dcdce65767a 100644 --- a/src/react/internal/cache/SuspenseCache.ts +++ b/src/react/internal/cache/SuspenseCache.ts @@ -30,19 +30,26 @@ export class SuspenseCache { getQueryRef( cacheKey: CacheKey, - createObservable: () => ObservableQuery + createObservable: () => ObservableQuery, + trackUses: boolean = false ) { const ref = this.queryRefs.lookupArray(cacheKey) as { current?: InternalQueryReference; }; if (!ref.current) { - ref.current = new InternalQueryReference(createObservable(), { - autoDisposeTimeoutMs: this.options.autoDisposeTimeoutMs, - onDispose: () => { - delete ref.current; + ref.current = new InternalQueryReference( + createObservable(), + { + autoDisposeTimeoutMs: this.options.autoDisposeTimeoutMs, + onDispose: () => { + delete ref.current; + }, }, - }); + trackUses + ); + } else if (trackUses) { + ref.current.newUsage(); } return ref.current; From b364b10ac5915968d2d7dd33cbde50350fee15a0 Mon Sep 17 00:00:00 2001 From: PiR1 Date: Wed, 20 Mar 2024 19:05:16 +0100 Subject: [PATCH 4/8] fix(useBackgroundQuery): better usage tracking --- .../__tests__/useBackgroundQuery.test.tsx | 53 +++++++++++++++++++ src/react/hooks/useBackgroundQuery.ts | 7 ++- src/react/internal/cache/QueryReference.ts | 25 +++++---- src/react/internal/cache/SuspenseCache.ts | 19 +++---- 4 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx index 54ad243d5ba..e1b2d3e30a3 100644 --- a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx +++ b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx @@ -111,6 +111,7 @@ function createErrorProfiler() { }, }); } + function createDefaultProfiler() { return createProfiler({ initialSnapshot: { @@ -562,6 +563,53 @@ it("does not prematurely dispose of the queryRef when using strict mode", async expect(client).toHaveSuspenseCacheEntryUsing(query); }); +it("disposes of the queryRef when unmounting before it is used by useReadQuery even if it has been rerendered", async () => { + const { query, mocks } = setupSimpleCase(); + const client = new ApolloClient({ + link: new MockLink(mocks), + cache: new InMemoryCache(), + }); + const user = userEvent.setup(); + + const Profiler = createDefaultProfiler(); + + function App() { + useTrackRenders(); + useBackgroundQuery(query); + + const [a, setA] = React.useState(0); + + return ( + <> + + + ); + } + + const { unmount } = renderWithClient(, { + client, + wrapper: Profiler, + }); + const button = screen.getByText("Increment"); + + await act(() => user.click(button)); + + { + const { renderedComponents } = await Profiler.takeRender(); + + expect(renderedComponents).toStrictEqual([App]); + } + + expect(client.getObservableQueries().size).toBe(1); + expect(client).toHaveSuspenseCacheEntryUsing(query); + + await wait(0); + + unmount(); + await wait(0); + expect(client.getObservableQueries().size).toBe(0); +}); + it("allows the client to be overridden", async () => { const { query } = setupSimpleCase(); @@ -1101,6 +1149,7 @@ it("works with startTransition to change variables", async () => { completed: boolean; }; } + const user = userEvent.setup(); const query: TypedDocumentNode = gql` @@ -4305,6 +4354,7 @@ describe("refetch", () => { completed: boolean; }; } + const user = userEvent.setup(); const query: TypedDocumentNode = gql` @@ -4553,6 +4603,7 @@ describe("refetch", () => { completed: boolean; }; } + const user = userEvent.setup(); const query: TypedDocumentNode = gql` @@ -5162,9 +5213,11 @@ describe("fetchMore", () => { name: string; completed: boolean; } + interface Data { todos: Todo[]; } + const user = userEvent.setup(); const query: TypedDocumentNode = gql` diff --git a/src/react/hooks/useBackgroundQuery.ts b/src/react/hooks/useBackgroundQuery.ts index 6f0e2df4108..9623002170e 100644 --- a/src/react/hooks/useBackgroundQuery.ts +++ b/src/react/hooks/useBackgroundQuery.ts @@ -224,10 +224,8 @@ function _useBackgroundQuery< ...([] as any[]).concat(queryKey), ]; - const queryRef = suspenseCache.getQueryRef( - cacheKey, - () => client.watchQuery(watchQueryOptions as WatchQueryOptions), - true + const queryRef = suspenseCache.getQueryRef(cacheKey, () => + client.watchQuery(watchQueryOptions as WatchQueryOptions) ); const [wrappedQueryRef, setWrappedQueryRef] = React.useState( @@ -264,6 +262,7 @@ function _useBackgroundQuery< ); React.useEffect(() => { + queryRef.newUsage(); return () => { queryRef.disposeOnUnmount(); }; diff --git a/src/react/internal/cache/QueryReference.ts b/src/react/internal/cache/QueryReference.ts index ac0a639ac85..31b1ab70812 100644 --- a/src/react/internal/cache/QueryReference.ts +++ b/src/react/internal/cache/QueryReference.ts @@ -160,19 +160,17 @@ export class InternalQueryReference { private reject: ((error: unknown) => void) | undefined; private references = 0; - private nbOfUse = 0; + private numberOfUse = 0; constructor( observable: ObservableQuery, - options: InternalQueryReferenceOptions, - trackUses: boolean = false + options: InternalQueryReferenceOptions ) { this.handleNext = this.handleNext.bind(this); this.handleError = this.handleError.bind(this); this.dispose = this.dispose.bind(this); this.observable = observable; this.autoDisposeTimeoutMs = options.autoDisposeTimeoutMs ?? 30_000; - this.nbOfUse = trackUses ? 1 : 0; if (options.onDispose) { this.onDispose = options.onDispose; @@ -260,16 +258,21 @@ export class InternalQueryReference { } newUsage() { - this.nbOfUse++; - clearTimeout(this.autoDisposeTimeoutId); - this.startDisposeTimer(); + this.numberOfUse++; + if (!this.references) { + clearTimeout(this.autoDisposeTimeoutId); + this.startDisposeTimer(); + } } disposeOnUnmount() { - this.nbOfUse--; - if (!this.nbOfUse && !this.references) { - this.dispose(); - } + this.numberOfUse--; + // Wait before fully disposing in case the app is running in strict mode. + setTimeout(() => { + if (!this.numberOfUse && !this.references) { + this.dispose(); + } + }); } didChangeOptions(watchQueryOptions: ObservedOptions) { diff --git a/src/react/internal/cache/SuspenseCache.ts b/src/react/internal/cache/SuspenseCache.ts index dcdce65767a..d66eb905a5a 100644 --- a/src/react/internal/cache/SuspenseCache.ts +++ b/src/react/internal/cache/SuspenseCache.ts @@ -30,26 +30,19 @@ export class SuspenseCache { getQueryRef( cacheKey: CacheKey, - createObservable: () => ObservableQuery, - trackUses: boolean = false + createObservable: () => ObservableQuery ) { const ref = this.queryRefs.lookupArray(cacheKey) as { current?: InternalQueryReference; }; if (!ref.current) { - ref.current = new InternalQueryReference( - createObservable(), - { - autoDisposeTimeoutMs: this.options.autoDisposeTimeoutMs, - onDispose: () => { - delete ref.current; - }, + ref.current = new InternalQueryReference(createObservable(), { + autoDisposeTimeoutMs: this.options.autoDisposeTimeoutMs, + onDispose: () => { + delete ref.current; }, - trackUses - ); - } else if (trackUses) { - ref.current.newUsage(); + }); } return ref.current; From a381c3f5b2433fedebd8c2feed92c5a47c764ca9 Mon Sep 17 00:00:00 2001 From: PiR1 Date: Thu, 21 Mar 2024 23:26:23 +0100 Subject: [PATCH 5/8] improvement(useBackgroundQuery): naming & implementation of softReferences --- .changeset/fast-roses-kick.md | 2 +- src/react/hooks/useBackgroundQuery.ts | 7 +-- src/react/internal/cache/QueryReference.ts | 67 +++++++++++----------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/.changeset/fast-roses-kick.md b/.changeset/fast-roses-kick.md index 60c9e5c74bb..592ee93e736 100644 --- a/.changeset/fast-roses-kick.md +++ b/.changeset/fast-roses-kick.md @@ -2,4 +2,4 @@ "@apollo/client": patch --- -useBackgroundQuery, handle ref disposal if unmount before used +Immediately dispose of the `queryRef` if `useBackgroundQuery` unmounts before the auto dispose timeout kicks in. diff --git a/src/react/hooks/useBackgroundQuery.ts b/src/react/hooks/useBackgroundQuery.ts index 9623002170e..ba5f8c19221 100644 --- a/src/react/hooks/useBackgroundQuery.ts +++ b/src/react/hooks/useBackgroundQuery.ts @@ -261,12 +261,7 @@ function _useBackgroundQuery< [queryRef] ); - React.useEffect(() => { - queryRef.newUsage(); - return () => { - queryRef.disposeOnUnmount(); - }; - }, [queryRef]); + React.useEffect(() => queryRef.softRetain(), [queryRef]); return [ didFetchResult.current ? wrappedQueryRef : void 0, diff --git a/src/react/internal/cache/QueryReference.ts b/src/react/internal/cache/QueryReference.ts index 31b1ab70812..4b3ebb961a3 100644 --- a/src/react/internal/cache/QueryReference.ts +++ b/src/react/internal/cache/QueryReference.ts @@ -154,13 +154,12 @@ export class InternalQueryReference { private subscription!: ObservableSubscription; private listeners = new Set>(); private autoDisposeTimeoutId?: NodeJS.Timeout; - private readonly autoDisposeTimeoutMs?: number; private resolve: ((result: ApolloQueryResult) => void) | undefined; private reject: ((error: unknown) => void) | undefined; private references = 0; - private numberOfUse = 0; + private softReferences = 0; constructor( observable: ObservableQuery, @@ -170,7 +169,6 @@ export class InternalQueryReference { this.handleError = this.handleError.bind(this); this.dispose = this.dispose.bind(this); this.observable = observable; - this.autoDisposeTimeoutMs = options.autoDisposeTimeoutMs ?? 30_000; if (options.onDispose) { this.onDispose = options.onDispose; @@ -179,13 +177,23 @@ export class InternalQueryReference { this.setResult(); this.subscribeToQuery(); + // Start a timer that will automatically dispose of the query if the + // suspended resource does not use this queryRef in the given time. This + // helps prevent memory leaks when a component has unmounted before the + // query has finished loading. + const startDisposeTimer = () => { + if (!this.references) { + this.autoDisposeTimeoutId = setTimeout( + this.dispose, + options.autoDisposeTimeoutMs ?? 30_000 + ); + } + }; + // We wait until the request has settled to ensure we don't dispose of the // query ref before the request finishes, otherwise we would leave the // promise in a pending state rendering the suspense boundary indefinitely. - this.promise.then( - this.startDisposeTimer.bind(this), - this.startDisposeTimer.bind(this) - ); + this.promise.then(startDisposeTimer, startDisposeTimer); } get disposed() { @@ -196,19 +204,6 @@ export class InternalQueryReference { return this.observable.options; } - // Start a timer that will automatically dispose of the query if the - // suspended resource does not use this queryRef in the given time. This - // helps prevent memory leaks when a component has unmounted before the - // query has finished loading. - startDisposeTimer() { - if (!this.references) { - this.autoDisposeTimeoutId = setTimeout( - this.dispose, - this.autoDisposeTimeoutMs ?? 30_000 - ); - } - } - reinitialize() { const { observable } = this; @@ -257,22 +252,26 @@ export class InternalQueryReference { }; } - newUsage() { - this.numberOfUse++; - if (!this.references) { - clearTimeout(this.autoDisposeTimeoutId); - this.startDisposeTimer(); - } - } + softRetain() { + this.softReferences++; + let disposed = false; - disposeOnUnmount() { - this.numberOfUse--; - // Wait before fully disposing in case the app is running in strict mode. - setTimeout(() => { - if (!this.numberOfUse && !this.references) { - this.dispose(); + return () => { + // Tracking if this has already been called helps ensure that + // multiple calls to this function won't decrement the reference + // counter more than it should. Subsequent calls just result in a noop. + if (disposed) { + return } - }); + + disposed = true; + this.softReferences--; + setTimeout(() => { + if (!this.softReferences && !this.references) { + this.dispose(); + } + }); + } } didChangeOptions(watchQueryOptions: ObservedOptions) { From 626ebf0c93058d18cfb20af4c23ef5406240373d Mon Sep 17 00:00:00 2001 From: PiR1 Date: Thu, 21 Mar 2024 23:37:51 +0100 Subject: [PATCH 6/8] style(queryReference): apply prettier --- src/react/internal/cache/QueryReference.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/react/internal/cache/QueryReference.ts b/src/react/internal/cache/QueryReference.ts index 4b3ebb961a3..d991dc00077 100644 --- a/src/react/internal/cache/QueryReference.ts +++ b/src/react/internal/cache/QueryReference.ts @@ -261,7 +261,7 @@ export class InternalQueryReference { // multiple calls to this function won't decrement the reference // counter more than it should. Subsequent calls just result in a noop. if (disposed) { - return + return; } disposed = true; @@ -271,7 +271,7 @@ export class InternalQueryReference { this.dispose(); } }); - } + }; } didChangeOptions(watchQueryOptions: ObservedOptions) { From a1198d009f461eff29da3047ded118d7569a40e5 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Mar 2024 16:46:10 -0600 Subject: [PATCH 7/8] Update size limits --- .size-limits.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limits.json b/.size-limits.json index 10e91f0ebf7..3dc2aae6853 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 39277, + "dist/apollo-client.min.cjs": 39319, "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32630 } From 10833467a70f58c386a395061dc7daf9ee082fd6 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Mar 2024 16:47:04 -0600 Subject: [PATCH 8/8] Run extract api --- .api-reports/api-report-react.md | 2 ++ .api-reports/api-report-react_hooks.md | 2 ++ .api-reports/api-report-react_internal.md | 2 ++ .api-reports/api-report.md | 2 ++ 4 files changed, 8 insertions(+) diff --git a/.api-reports/api-report-react.md b/.api-reports/api-report-react.md index d604f535089..a12089d47fc 100644 --- a/.api-reports/api-report-react.md +++ b/.api-reports/api-report-react.md @@ -953,6 +953,8 @@ class InternalQueryReference { // (undocumented) retain(): () => void; // (undocumented) + softRetain(): () => void; + // (undocumented) get watchQueryOptions(): WatchQueryOptions; } diff --git a/.api-reports/api-report-react_hooks.md b/.api-reports/api-report-react_hooks.md index e87875b811a..8e157061ac6 100644 --- a/.api-reports/api-report-react_hooks.md +++ b/.api-reports/api-report-react_hooks.md @@ -895,6 +895,8 @@ class InternalQueryReference { // (undocumented) retain(): () => void; // (undocumented) + softRetain(): () => void; + // (undocumented) get watchQueryOptions(): WatchQueryOptions; } diff --git a/.api-reports/api-report-react_internal.md b/.api-reports/api-report-react_internal.md index 84afcfd091a..d81159f41cd 100644 --- a/.api-reports/api-report-react_internal.md +++ b/.api-reports/api-report-react_internal.md @@ -885,6 +885,8 @@ export class InternalQueryReference { // (undocumented) retain(): () => void; // (undocumented) + softRetain(): () => void; + // (undocumented) get watchQueryOptions(): WatchQueryOptions; } diff --git a/.api-reports/api-report.md b/.api-reports/api-report.md index ebbea8fb589..6d1e721d379 100644 --- a/.api-reports/api-report.md +++ b/.api-reports/api-report.md @@ -1328,6 +1328,8 @@ class InternalQueryReference { // (undocumented) retain(): () => void; // (undocumented) + softRetain(): () => void; + // (undocumented) get watchQueryOptions(): WatchQueryOptions; }